Bomberman
Bomberman est une série de jeux vidéo de Hudson Soft où le joueur incarne un poseur de bombes, le but étant de faire exploser les adversaires/ennemis pour gagner.
nuklear.h
Go to the documentation of this file.
1 /*
212 */
213 #ifndef NK_SINGLE_FILE
214  #define NK_SINGLE_FILE
215 #endif
216 
217 #ifndef NK_NUKLEAR_H_
218 #define NK_NUKLEAR_H_
219 
220 #ifdef __cplusplus
221 extern "C" {
222 #endif
223 /*
224  * ==============================================================
225  *
226  * CONSTANTS
227  *
228  * ===============================================================
229  */
230 #define NK_UNDEFINED (-1.0f)
231 #define NK_UTF_INVALID 0xFFFD /* internal invalid utf8 rune */
232 #define NK_UTF_SIZE 4 /* describes the number of bytes a glyph consists of*/
233 #ifndef NK_INPUT_MAX
234  #define NK_INPUT_MAX 16
235 #endif
236 #ifndef NK_MAX_NUMBER_BUFFER
237  #define NK_MAX_NUMBER_BUFFER 64
238 #endif
239 #ifndef NK_SCROLLBAR_HIDING_TIMEOUT
240  #define NK_SCROLLBAR_HIDING_TIMEOUT 4.0f
241 #endif
242 /*
243  * ==============================================================
244  *
245  * HELPER
246  *
247  * ===============================================================
248  */
249 #ifndef NK_API
250  #ifdef NK_PRIVATE
251  #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199409L))
252  #define NK_API static inline
253  #elif defined(__cplusplus)
254  #define NK_API static inline
255  #else
256  #define NK_API static
257  #endif
258  #else
259  #define NK_API extern
260  #endif
261 #endif
262 #ifndef NK_LIB
263  #ifdef NK_SINGLE_FILE
264  #define NK_LIB static
265  #else
266  #define NK_LIB extern
267  #endif
268 #endif
269 
270 #define NK_INTERN static
271 #define NK_STORAGE static
272 #define NK_GLOBAL static
273 
274 #define NK_FLAG(x) (1 << (x))
275 #define NK_STRINGIFY(x) #x
276 #define NK_MACRO_STRINGIFY(x) NK_STRINGIFY(x)
277 #define NK_STRING_JOIN_IMMEDIATE(arg1, arg2) arg1 ## arg2
278 #define NK_STRING_JOIN_DELAY(arg1, arg2) NK_STRING_JOIN_IMMEDIATE(arg1, arg2)
279 #define NK_STRING_JOIN(arg1, arg2) NK_STRING_JOIN_DELAY(arg1, arg2)
280 
281 #ifdef _MSC_VER
282  #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__COUNTER__)
283 #else
284  #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__LINE__)
285 #endif
286 
287 #ifndef NK_STATIC_ASSERT
288  #define NK_STATIC_ASSERT(exp) typedef char NK_UNIQUE_NAME(_dummy_array)[(exp)?1:-1]
289 #endif
290 
291 #ifndef NK_FILE_LINE
292 #ifdef _MSC_VER
293  #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__COUNTER__)
294 #else
295  #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__LINE__)
296 #endif
297 #endif
298 
299 #define NK_MIN(a,b) ((a) < (b) ? (a) : (b))
300 #define NK_MAX(a,b) ((a) < (b) ? (b) : (a))
301 #define NK_CLAMP(i,v,x) (NK_MAX(NK_MIN(v,x), i))
302 
303 #ifdef NK_INCLUDE_STANDARD_VARARGS
304  #if defined(_MSC_VER) && (_MSC_VER >= 1600) /* VS 2010 and above */
305  #include <sal.h>
306  #define NK_PRINTF_FORMAT_STRING _Printf_format_string_
307  #else
308  #define NK_PRINTF_FORMAT_STRING
309  #endif
310  #if defined(__GNUC__)
311  #define NK_PRINTF_VARARG_FUNC(fmtargnumber) __attribute__((format(__printf__, fmtargnumber, fmtargnumber+1)))
312  #define NK_PRINTF_VALIST_FUNC(fmtargnumber) __attribute__((format(__printf__, fmtargnumber, 0)))
313  #else
314  #define NK_PRINTF_VARARG_FUNC(fmtargnumber)
315  #define NK_PRINTF_VALIST_FUNC(fmtargnumber)
316  #endif
317 #endif
318 
319 /*
320  * ===============================================================
321  *
322  * BASIC
323  *
324  * ===============================================================
325  */
326 #ifdef NK_INCLUDE_FIXED_TYPES
327  #include <stdint.h>
328  #define NK_INT8 int8_t
329  #define NK_UINT8 uint8_t
330  #define NK_INT16 int16_t
331  #define NK_UINT16 uint16_t
332  #define NK_INT32 int32_t
333  #define NK_UINT32 uint32_t
334  #define NK_SIZE_TYPE uintptr_t
335  #define NK_POINTER_TYPE uintptr_t
336 #else
337  #ifndef NK_INT8
338  #define NK_INT8 char
339  #endif
340  #ifndef NK_UINT8
341  #define NK_UINT8 unsigned char
342  #endif
343  #ifndef NK_INT16
344  #define NK_INT16 signed short
345  #endif
346  #ifndef NK_UINT16
347  #define NK_UINT16 unsigned short
348  #endif
349  #ifndef NK_INT32
350  #if defined(_MSC_VER)
351  #define NK_INT32 __int32
352  #else
353  #define NK_INT32 signed int
354  #endif
355  #endif
356  #ifndef NK_UINT32
357  #if defined(_MSC_VER)
358  #define NK_UINT32 unsigned __int32
359  #else
360  #define NK_UINT32 unsigned int
361  #endif
362  #endif
363  #ifndef NK_SIZE_TYPE
364  #if defined(_WIN64) && defined(_MSC_VER)
365  #define NK_SIZE_TYPE unsigned __int64
366  #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
367  #define NK_SIZE_TYPE unsigned __int32
368  #elif defined(__GNUC__) || defined(__clang__)
369  #if defined(__x86_64__) || defined(__ppc64__)
370  #define NK_SIZE_TYPE unsigned long
371  #else
372  #define NK_SIZE_TYPE unsigned int
373  #endif
374  #else
375  #define NK_SIZE_TYPE unsigned long
376  #endif
377  #endif
378  #ifndef NK_POINTER_TYPE
379  #if defined(_WIN64) && defined(_MSC_VER)
380  #define NK_POINTER_TYPE unsigned __int64
381  #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
382  #define NK_POINTER_TYPE unsigned __int32
383  #elif defined(__GNUC__) || defined(__clang__)
384  #if defined(__x86_64__) || defined(__ppc64__)
385  #define NK_POINTER_TYPE unsigned long
386  #else
387  #define NK_POINTER_TYPE unsigned int
388  #endif
389  #else
390  #define NK_POINTER_TYPE unsigned long
391  #endif
392  #endif
393 #endif
394 
395 typedef NK_INT8 nk_char;
400 typedef NK_INT32 nk_int;
404 
405 typedef nk_uint nk_hash;
407 typedef nk_uint nk_rune;
408 
409 /* Make sure correct type size:
410  * This will fire with a negative subscript error if the type sizes
411  * are set incorrectly by the compiler, and compile out if not */
412 NK_STATIC_ASSERT(sizeof(nk_short) == 2);
413 NK_STATIC_ASSERT(sizeof(nk_ushort) == 2);
414 NK_STATIC_ASSERT(sizeof(nk_uint) == 4);
415 NK_STATIC_ASSERT(sizeof(nk_int) == 4);
416 NK_STATIC_ASSERT(sizeof(nk_byte) == 1);
417 NK_STATIC_ASSERT(sizeof(nk_flags) >= 4);
418 NK_STATIC_ASSERT(sizeof(nk_rune) >= 4);
419 NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*));
420 NK_STATIC_ASSERT(sizeof(nk_ptr) >= sizeof(void*));
421 
422 /* ============================================================================
423  *
424  * API
425  *
426  * =========================================================================== */
427 struct nk_buffer;
428 struct nk_allocator;
429 struct nk_command_buffer;
430 struct nk_draw_command;
431 struct nk_convert_config;
432 struct nk_style_item;
433 struct nk_text_edit;
434 struct nk_draw_list;
435 struct nk_user_font;
436 struct nk_panel;
437 struct nk_context;
438 struct nk_draw_vertex_layout_element;
439 struct nk_style_button;
440 struct nk_style_toggle;
441 struct nk_style_selectable;
442 struct nk_style_slide;
443 struct nk_style_progress;
444 struct nk_style_scrollbar;
445 struct nk_style_edit;
446 struct nk_style_property;
447 struct nk_style_chart;
448 struct nk_style_combo;
449 struct nk_style_tab;
451 struct nk_style_window;
452 
454 struct nk_color {nk_byte r,g,b,a;};
455 struct nk_colorf {float r,g,b,a;};
456 struct nk_vec2 {float x,y;};
457 struct nk_vec2i {short x, y;};
458 struct nk_rect {float x,y,w,h;};
459 struct nk_recti {short x,y,w,h;};
460 typedef char nk_glyph[NK_UTF_SIZE];
461 typedef union {void *ptr; int id;} nk_handle;
462 struct nk_image {nk_handle handle;unsigned short w,h;unsigned short region[4];};
463 struct nk_cursor {struct nk_image img; struct nk_vec2 size, offset;};
464 struct nk_scroll {nk_uint x, y;};
465 
478 
479 typedef void*(*nk_plugin_alloc)(nk_handle, void *old, nk_size);
480 typedef void (*nk_plugin_free)(nk_handle, void *old);
481 typedef int(*nk_plugin_filter)(const struct nk_text_edit*, nk_rune unicode);
482 typedef void(*nk_plugin_paste)(nk_handle, struct nk_text_edit*);
483 typedef void(*nk_plugin_copy)(nk_handle, const char*, int len);
484 
485 struct nk_allocator {
489 };
505 };
506 /* =============================================================================
507  *
508  * CONTEXT
509  *
510  * =============================================================================*/
511 /*/// ### Context
543  */
544 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
545 /*/// #### nk_init_default
560 */
561 NK_API int nk_init_default(struct nk_context*, const struct nk_user_font*);
562 #endif
563 /*/// #### nk_init_fixed
585 */
586 NK_API int nk_init_fixed(struct nk_context*, void *memory, nk_size size, const struct nk_user_font*);
587 /*/// #### nk_init
603 */
604 NK_API int nk_init(struct nk_context*, struct nk_allocator*, const struct nk_user_font*);
605 /*/// #### nk_init_custom
622 */
623 NK_API int nk_init_custom(struct nk_context*, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font*);
624 /*/// #### nk_clear
636 */
637 NK_API void nk_clear(struct nk_context*);
638 /*/// #### nk_free
649 */
650 NK_API void nk_free(struct nk_context*);
651 #ifdef NK_INCLUDE_COMMAND_USERDATA
652 /*/// #### nk_set_user_data
663 */
664 NK_API void nk_set_user_data(struct nk_context*, nk_handle handle);
665 #endif
666 /* =============================================================================
667  *
668  * INPUT
669  *
670  * =============================================================================*/
671 /*/// ### Input
731 */
732 enum nk_keys {
747  /* Shortcuts: text field */
760  /* Shortcuts: scrollbar */
766 };
773 };
774 /*/// #### nk_input_begin
785 */
786 NK_API void nk_input_begin(struct nk_context*);
787 /*/// #### nk_input_motion
799 */
800 NK_API void nk_input_motion(struct nk_context*, int x, int y);
801 /*/// #### nk_input_key
813 */
814 NK_API void nk_input_key(struct nk_context*, enum nk_keys, int down);
815 /*/// #### nk_input_button
829 */
830 NK_API void nk_input_button(struct nk_context*, enum nk_buttons, int x, int y, int down);
831 /*/// #### nk_input_scroll
843 */
844 NK_API void nk_input_scroll(struct nk_context*, struct nk_vec2 val);
845 /*/// #### nk_input_char
861 */
862 NK_API void nk_input_char(struct nk_context*, char);
863 /*/// #### nk_input_glyph
878 */
879 NK_API void nk_input_glyph(struct nk_context*, const nk_glyph);
880 /*/// #### nk_input_unicode
894 */
896 /*/// #### nk_input_end
907 */
908 NK_API void nk_input_end(struct nk_context*);
909 /* =============================================================================
910  *
911  * DRAWING
912  *
913  * =============================================================================*/
914 /*/// ### Drawing
1131 */
1139 };
1141  nk_handle texture; /* texture handle to a texture with a white pixel */
1142  struct nk_vec2 uv; /* coordinates to a white pixel in the texture */
1143 };
1145  float global_alpha; /* global alpha value */
1146  enum nk_anti_aliasing line_AA; /* line anti-aliasing flag can be turned off if you are tight on memory */
1147  enum nk_anti_aliasing shape_AA; /* shape anti-aliasing flag can be turned off if you are tight on memory */
1148  unsigned circle_segment_count; /* number of segments used for circles: default to 22 */
1149  unsigned arc_segment_count; /* number of segments used for arcs: default to 22 */
1150  unsigned curve_segment_count; /* number of segments used for curves: default to 22 */
1151  struct nk_draw_null_texture null; /* handle to texture with a white pixel for shape drawing */
1152  const struct nk_draw_vertex_layout_element *vertex_layout; /* describes the vertex output format and packing */
1153  nk_size vertex_size; /* sizeof one vertex for vertex packing */
1154  nk_size vertex_alignment; /* vertex alignment: Can be obtained by NK_ALIGNOF */
1155 };
1156 /*/// #### nk__begin
1169 */
1170 NK_API const struct nk_command* nk__begin(struct nk_context*);
1171 /*/// #### nk__next
1184 */
1185 NK_API const struct nk_command* nk__next(struct nk_context*, const struct nk_command*);
1186 /*/// #### nk_foreach
1199 */
1200 #define nk_foreach(c, ctx) for((c) = nk__begin(ctx); (c) != 0; (c) = nk__next(ctx,c))
1201 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
1202 /*/// #### nk_convert
1210 // struct nk_buffer *vertices, struct nk_buffer *elements, const struct nk_convert_config*);
1230 */
1231 NK_API nk_flags nk_convert(struct nk_context*, struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements, const struct nk_convert_config*);
1232 /*/// #### nk__draw_begin
1245 */
1246 NK_API const struct nk_draw_command* nk__draw_begin(const struct nk_context*, const struct nk_buffer*);
1247 /*/// #### nk__draw_end
1260 */
1261 NK_API const struct nk_draw_command* nk__draw_end(const struct nk_context*, const struct nk_buffer*);
1262 /*/// #### nk__draw_next
1276 */
1277 NK_API const struct nk_draw_command* nk__draw_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_context*);
1278 /*/// #### nk_draw_foreach
1290 */
1291 #define nk_draw_foreach(cmd,ctx, b) for((cmd)=nk__draw_begin(ctx, b); (cmd)!=0; (cmd)=nk__draw_next(cmd, b, ctx))
1292 #endif
1293 /* =============================================================================
1294  *
1295  * WINDOW
1296  *
1297  * =============================================================================
1382 //
1403 //
1408 //
1414 */
1415 /*
1437 */
1450 };
1451 /*/// #### nk_begin
1468 */
1469 NK_API int nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags);
1470 /*/// #### nk_begin_titled
1488 */
1489 NK_API int nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags);
1490 /*/// #### nk_end
1501 */
1502 NK_API void nk_end(struct nk_context *ctx);
1503 /*/// #### nk_window_find
1517 */
1518 NK_API struct nk_window *nk_window_find(struct nk_context *ctx, const char *name);
1519 /*/// #### nk_window_get_bounds
1533 */
1534 NK_API struct nk_rect nk_window_get_bounds(const struct nk_context *ctx);
1535 /*/// #### nk_window_get_bounds
1549 */
1550 NK_API struct nk_vec2 nk_window_get_position(const struct nk_context *ctx);
1551 /*/// #### nk_window_get_size
1565 */
1566 NK_API struct nk_vec2 nk_window_get_size(const struct nk_context*);
1567 /*/// #### nk_window_get_width
1581 */
1582 NK_API float nk_window_get_width(const struct nk_context*);
1583 /*/// #### nk_window_get_height
1597 */
1598 NK_API float nk_window_get_height(const struct nk_context*);
1599 /*/// #### nk_window_get_panel
1615 */
1617 /*/// #### nk_window_get_content_region
1634 */
1636 /*/// #### nk_window_get_content_region_min
1653 */
1655 /*/// #### nk_window_get_content_region_max
1672 */
1674 /*/// #### nk_window_get_content_region_size
1690 */
1692 /*/// #### nk_window_get_canvas
1709 */
1711 /*/// #### nk_window_has_focus
1724 */
1725 NK_API int nk_window_has_focus(const struct nk_context*);
1726 /*/// #### nk_window_is_hovered
1739 */
1741 /*/// #### nk_window_is_collapsed
1754 */
1755 NK_API int nk_window_is_collapsed(struct nk_context *ctx, const char *name);
1756 /*/// #### nk_window_is_closed
1768 */
1769 NK_API int nk_window_is_closed(struct nk_context*, const char*);
1770 /*/// #### nk_window_is_hidden
1782 */
1783 NK_API int nk_window_is_hidden(struct nk_context*, const char*);
1784 /*/// #### nk_window_is_active
1796 */
1797 NK_API int nk_window_is_active(struct nk_context*, const char*);
1798 /*/// #### nk_window_is_any_hovered
1809 */
1811 /*/// #### nk_item_is_any_active
1824 */
1826 /*/// #### nk_window_set_bounds
1837 */
1838 NK_API void nk_window_set_bounds(struct nk_context*, const char *name, struct nk_rect bounds);
1839 /*/// #### nk_window_set_position
1850 */
1851 NK_API void nk_window_set_position(struct nk_context*, const char *name, struct nk_vec2 pos);
1852 /*/// #### nk_window_set_size
1863 */
1864 NK_API void nk_window_set_size(struct nk_context*, const char *name, struct nk_vec2);
1865 /*/// #### nk_window_set_focus
1875 */
1876 NK_API void nk_window_set_focus(struct nk_context*, const char *name);
1877 /*/// #### nk_window_close
1887 */
1888 NK_API void nk_window_close(struct nk_context *ctx, const char *name);
1889 /*/// #### nk_window_collapse
1900 */
1901 NK_API void nk_window_collapse(struct nk_context*, const char *name, enum nk_collapse_states state);
1902 /*/// #### nk_window_collapse_if
1914 */
1915 NK_API void nk_window_collapse_if(struct nk_context*, const char *name, enum nk_collapse_states, int cond);
1916 /*/// #### nk_window_show
1927 */
1928 NK_API void nk_window_show(struct nk_context*, const char *name, enum nk_show_states);
1929 /*/// #### nk_window_show_if
1941 */
1942 NK_API void nk_window_show_if(struct nk_context*, const char *name, enum nk_show_states, int cond);
1943 /* =============================================================================
1944  *
1945  * LAYOUT
1946  *
1947  * =============================================================================
2192 //
2199 //
2205 //
2209 //
2215 */
2216 /*/// #### nk_layout_set_min_row_height
2230 */
2231 NK_API void nk_layout_set_min_row_height(struct nk_context*, float height);
2232 /*/// #### nk_layout_reset_min_row_height
2241 */
2243 /*/// #### nk_layout_widget_bounds
2254 */
2256 /*/// #### nk_layout_ratio_from_pixel
2268 */
2269 NK_API float nk_layout_ratio_from_pixel(struct nk_context*, float pixel_width);
2270 /*/// #### nk_layout_row_dynamic
2283 */
2284 NK_API void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols);
2285 /*/// #### nk_layout_row_dynamic
2299 */
2300 NK_API void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols);
2301 /*/// #### nk_layout_row_begin
2313 */
2314 NK_API void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols);
2315 /*/// #### nk_layout_row_push
2325 */
2326 NK_API void nk_layout_row_push(struct nk_context*, float value);
2327 /*/// #### nk_layout_row_end
2336 */
2337 NK_API void nk_layout_row_end(struct nk_context*);
2338 /*/// #### nk_layout_row
2350 */
2351 NK_API void nk_layout_row(struct nk_context*, enum nk_layout_format, float height, int cols, const float *ratio);
2352 /*/// #### nk_layout_row_template_begin
2362 */
2363 NK_API void nk_layout_row_template_begin(struct nk_context*, float row_height);
2364 /*/// #### nk_layout_row_template_push_dynamic
2374 */
2376 /*/// #### nk_layout_row_template_push_variable
2386 */
2387 NK_API void nk_layout_row_template_push_variable(struct nk_context*, float min_width);
2388 /*/// #### nk_layout_row_template_push_static
2398 */
2399 NK_API void nk_layout_row_template_push_static(struct nk_context*, float width);
2400 /*/// #### nk_layout_row_template_end
2409 */
2411 /*/// #### nk_layout_space_begin
2423 */
2424 NK_API void nk_layout_space_begin(struct nk_context*, enum nk_layout_format, float height, int widget_count);
2425 /*/// #### nk_layout_space_push
2435 */
2436 NK_API void nk_layout_space_push(struct nk_context*, struct nk_rect bounds);
2437 /*/// #### nk_layout_space_end
2446 */
2447 NK_API void nk_layout_space_end(struct nk_context*);
2448 /*/// #### nk_layout_space_bounds
2459 */
2461 /*/// #### nk_layout_space_to_screen
2473 */
2475 /*/// #### nk_layout_space_to_screen
2487 */
2488 NK_API struct nk_vec2 nk_layout_space_to_local(struct nk_context*, struct nk_vec2);
2489 /*/// #### nk_layout_space_rect_to_screen
2501 */
2503 /*/// #### nk_layout_space_rect_to_local
2515 */
2517 /* =============================================================================
2518  *
2519  * GROUP
2520  *
2521  * =============================================================================
2589 // nk_clear(&ctx);
2602 */
2603 /*/// #### nk_group_begin
2616 */
2617 NK_API int nk_group_begin(struct nk_context*, const char *title, nk_flags);
2618 /*/// #### nk_group_begin_titled
2632 */
2633 NK_API int nk_group_begin_titled(struct nk_context*, const char *name, const char *title, nk_flags);
2634 /*/// #### nk_group_end
2643 */
2644 NK_API void nk_group_end(struct nk_context*);
2645 /*/// #### nk_group_scrolled_offset_begin
2661 */
2662 NK_API int nk_group_scrolled_offset_begin(struct nk_context*, nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags);
2663 /*/// #### nk_group_scrolled_begin
2678 */
2679 NK_API int nk_group_scrolled_begin(struct nk_context*, struct nk_scroll *off, const char *title, nk_flags);
2680 /*/// #### nk_group_scrolled_end
2689 */
2691 /* =============================================================================
2692  *
2693  * TREE
2694  *
2695  * =============================================================================
2750 //
2760 */
2761 /*/// #### nk_tree_push
2781 */
2782 #define nk_tree_push(ctx, type, title, state) nk_tree_push_hashed(ctx, type, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),__LINE__)
2783 /*/// #### nk_tree_push_id
2798 */
2799 #define nk_tree_push_id(ctx, type, title, state, id) nk_tree_push_hashed(ctx, type, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),id)
2800 /*/// #### nk_tree_push_hashed
2818 */
2819 NK_API int nk_tree_push_hashed(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed);
2820 /*/// #### nk_tree_image_push
2831 //
2841 */
2842 #define nk_tree_image_push(ctx, type, img, title, state) nk_tree_image_push_hashed(ctx, type, img, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),__LINE__)
2843 /*/// #### nk_tree_image_push_id
2861 */
2862 #define nk_tree_image_push_id(ctx, type, img, title, state, id) nk_tree_image_push_hashed(ctx, type, img, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),id)
2863 /*/// #### nk_tree_image_push_hashed
2882 */
2883 NK_API int nk_tree_image_push_hashed(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed);
2884 /*/// #### nk_tree_pop
2893 */
2894 NK_API void nk_tree_pop(struct nk_context*);
2895 /*/// #### nk_tree_state_push
2909 */
2910 NK_API int nk_tree_state_push(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states *state);
2911 /*/// #### nk_tree_state_image_push
2926 */
2927 NK_API int nk_tree_state_image_push(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states *state);
2928 /*/// #### nk_tree_state_pop
2937 */
2938 NK_API void nk_tree_state_pop(struct nk_context*);
2939 
2940 #define nk_tree_element_push(ctx, type, title, state, sel) nk_tree_element_push_hashed(ctx, type, title, state, sel, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),__LINE__)
2941 #define nk_tree_element_push_id(ctx, type, title, state, sel, id) nk_tree_element_push_hashed(ctx, type, title, state, sel, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),id)
2942 NK_API int nk_tree_element_push_hashed(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, int *selected, const char *hash, int len, int seed);
2943 NK_API int nk_tree_element_image_push_hashed(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, int *selected, const char *hash, int len,int seed);
2944 NK_API void nk_tree_element_pop(struct nk_context*);
2945 
2946 /* =============================================================================
2947  *
2948  * LIST VIEW
2949  *
2950  * ============================================================================= */
2952 /* public: */
2953  int begin, end, count;
2954 /* private: */
2956  struct nk_context *ctx;
2959 };
2960 NK_API int nk_list_view_begin(struct nk_context*, struct nk_list_view *out, const char *id, nk_flags, int row_height, int row_count);
2961 NK_API void nk_list_view_end(struct nk_list_view*);
2962 /* =============================================================================
2963  *
2964  * WIDGET
2965  *
2966  * ============================================================================= */
2968  NK_WIDGET_INVALID, /* The widget cannot be seen and is completely out of view */
2969  NK_WIDGET_VALID, /* The widget is completely inside the window and can be updated and drawn */
2970  NK_WIDGET_ROM /* The widget is partially visible and cannot be updated */
2971 };
2974  NK_WIDGET_STATE_INACTIVE = NK_FLAG(2), /* widget is neither active nor hovered */
2975  NK_WIDGET_STATE_ENTERED = NK_FLAG(3), /* widget has been hovered on the current frame */
2976  NK_WIDGET_STATE_HOVER = NK_FLAG(4), /* widget is being hovered */
2977  NK_WIDGET_STATE_ACTIVED = NK_FLAG(5),/* widget is currently activated */
2978  NK_WIDGET_STATE_LEFT = NK_FLAG(6), /* widget is from this frame on not hovered anymore */
2981 };
2982 NK_API enum nk_widget_layout_states nk_widget(struct nk_rect*, const struct nk_context*);
2984 NK_API struct nk_rect nk_widget_bounds(struct nk_context*);
2986 NK_API struct nk_vec2 nk_widget_size(struct nk_context*);
2987 NK_API float nk_widget_width(struct nk_context*);
2988 NK_API float nk_widget_height(struct nk_context*);
2991 NK_API int nk_widget_has_mouse_click_down(struct nk_context*, enum nk_buttons, int down);
2992 NK_API void nk_spacing(struct nk_context*, int cols);
2993 /* =============================================================================
2994  *
2995  * TEXT
2996  *
2997  * ============================================================================= */
3005 };
3010 };
3011 NK_API void nk_text(struct nk_context*, const char*, int, nk_flags);
3012 NK_API void nk_text_colored(struct nk_context*, const char*, int, nk_flags, struct nk_color);
3013 NK_API void nk_text_wrap(struct nk_context*, const char*, int);
3014 NK_API void nk_text_wrap_colored(struct nk_context*, const char*, int, struct nk_color);
3015 NK_API void nk_label(struct nk_context*, const char*, nk_flags align);
3016 NK_API void nk_label_colored(struct nk_context*, const char*, nk_flags align, struct nk_color);
3017 NK_API void nk_label_wrap(struct nk_context*, const char*);
3018 NK_API void nk_label_colored_wrap(struct nk_context*, const char*, struct nk_color);
3019 NK_API void nk_image(struct nk_context*, struct nk_image);
3020 NK_API void nk_image_color(struct nk_context*, struct nk_image, struct nk_color);
3021 #ifdef NK_INCLUDE_STANDARD_VARARGS
3022 NK_API void nk_labelf(struct nk_context*, nk_flags, NK_PRINTF_FORMAT_STRING const char*, ...) NK_PRINTF_VARARG_FUNC(3);
3023 NK_API void nk_labelf_colored(struct nk_context*, nk_flags, struct nk_color, NK_PRINTF_FORMAT_STRING const char*,...) NK_PRINTF_VARARG_FUNC(4);
3024 NK_API void nk_labelf_wrap(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*,...) NK_PRINTF_VARARG_FUNC(2);
3025 NK_API void nk_labelf_colored_wrap(struct nk_context*, struct nk_color, NK_PRINTF_FORMAT_STRING const char*,...) NK_PRINTF_VARARG_FUNC(3);
3026 NK_API void nk_labelfv(struct nk_context*, nk_flags, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(3);
3027 NK_API void nk_labelfv_colored(struct nk_context*, nk_flags, struct nk_color, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(4);
3028 NK_API void nk_labelfv_wrap(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(2);
3029 NK_API void nk_labelfv_colored_wrap(struct nk_context*, struct nk_color, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(3);
3030 NK_API void nk_value_bool(struct nk_context*, const char *prefix, int);
3031 NK_API void nk_value_int(struct nk_context*, const char *prefix, int);
3032 NK_API void nk_value_uint(struct nk_context*, const char *prefix, unsigned int);
3033 NK_API void nk_value_float(struct nk_context*, const char *prefix, float);
3034 NK_API void nk_value_color_byte(struct nk_context*, const char *prefix, struct nk_color);
3035 NK_API void nk_value_color_float(struct nk_context*, const char *prefix, struct nk_color);
3036 NK_API void nk_value_color_hex(struct nk_context*, const char *prefix, struct nk_color);
3037 #endif
3038 /* =============================================================================
3039  *
3040  * BUTTON
3041  *
3042  * ============================================================================= */
3043 NK_API int nk_button_text(struct nk_context*, const char *title, int len);
3044 NK_API int nk_button_label(struct nk_context*, const char *title);
3045 NK_API int nk_button_color(struct nk_context*, struct nk_color);
3047 NK_API int nk_button_image(struct nk_context*, struct nk_image img);
3048 NK_API int nk_button_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags text_alignment);
3049 NK_API int nk_button_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
3050 NK_API int nk_button_image_label(struct nk_context*, struct nk_image img, const char*, nk_flags text_alignment);
3051 NK_API int nk_button_image_text(struct nk_context*, struct nk_image img, const char*, int, nk_flags alignment);
3052 NK_API int nk_button_text_styled(struct nk_context*, const struct nk_style_button*, const char *title, int len);
3053 NK_API int nk_button_label_styled(struct nk_context*, const struct nk_style_button*, const char *title);
3054 NK_API int nk_button_symbol_styled(struct nk_context*, const struct nk_style_button*, enum nk_symbol_type);
3055 NK_API int nk_button_image_styled(struct nk_context*, const struct nk_style_button*, struct nk_image img);
3056 NK_API int nk_button_symbol_text_styled(struct nk_context*,const struct nk_style_button*, enum nk_symbol_type, const char*, int, nk_flags alignment);
3057 NK_API int nk_button_symbol_label_styled(struct nk_context *ctx, const struct nk_style_button *style, enum nk_symbol_type symbol, const char *title, nk_flags align);
3058 NK_API int nk_button_image_label_styled(struct nk_context*,const struct nk_style_button*, struct nk_image img, const char*, nk_flags text_alignment);
3059 NK_API int nk_button_image_text_styled(struct nk_context*,const struct nk_style_button*, struct nk_image img, const char*, int, nk_flags alignment);
3063 /* =============================================================================
3064  *
3065  * CHECKBOX
3066  *
3067  * ============================================================================= */
3068 NK_API int nk_check_label(struct nk_context*, const char*, int active);
3069 NK_API int nk_check_text(struct nk_context*, const char*, int,int active);
3070 NK_API unsigned nk_check_flags_label(struct nk_context*, const char*, unsigned int flags, unsigned int value);
3071 NK_API unsigned nk_check_flags_text(struct nk_context*, const char*, int, unsigned int flags, unsigned int value);
3072 NK_API int nk_checkbox_label(struct nk_context*, const char*, int *active);
3073 NK_API int nk_checkbox_text(struct nk_context*, const char*, int, int *active);
3074 NK_API int nk_checkbox_flags_label(struct nk_context*, const char*, unsigned int *flags, unsigned int value);
3075 NK_API int nk_checkbox_flags_text(struct nk_context*, const char*, int, unsigned int *flags, unsigned int value);
3076 /* =============================================================================
3077  *
3078  * RADIO BUTTON
3079  *
3080  * ============================================================================= */
3081 NK_API int nk_radio_label(struct nk_context*, const char*, int *active);
3082 NK_API int nk_radio_text(struct nk_context*, const char*, int, int *active);
3083 NK_API int nk_option_label(struct nk_context*, const char*, int active);
3084 NK_API int nk_option_text(struct nk_context*, const char*, int, int active);
3085 /* =============================================================================
3086  *
3087  * SELECTABLE
3088  *
3089  * ============================================================================= */
3090 NK_API int nk_selectable_label(struct nk_context*, const char*, nk_flags align, int *value);
3091 NK_API int nk_selectable_text(struct nk_context*, const char*, int, nk_flags align, int *value);
3092 NK_API int nk_selectable_image_label(struct nk_context*,struct nk_image, const char*, nk_flags align, int *value);
3093 NK_API int nk_selectable_image_text(struct nk_context*,struct nk_image, const char*, int, nk_flags align, int *value);
3094 NK_API int nk_selectable_symbol_label(struct nk_context*,enum nk_symbol_type, const char*, nk_flags align, int *value);
3095 NK_API int nk_selectable_symbol_text(struct nk_context*,enum nk_symbol_type, const char*, int, nk_flags align, int *value);
3096 
3097 NK_API int nk_select_label(struct nk_context*, const char*, nk_flags align, int value);
3098 NK_API int nk_select_text(struct nk_context*, const char*, int, nk_flags align, int value);
3099 NK_API int nk_select_image_label(struct nk_context*, struct nk_image,const char*, nk_flags align, int value);
3100 NK_API int nk_select_image_text(struct nk_context*, struct nk_image,const char*, int, nk_flags align, int value);
3101 NK_API int nk_select_symbol_label(struct nk_context*,enum nk_symbol_type, const char*, nk_flags align, int value);
3102 NK_API int nk_select_symbol_text(struct nk_context*,enum nk_symbol_type, const char*, int, nk_flags align, int value);
3103 
3104 /* =============================================================================
3105  *
3106  * SLIDER
3107  *
3108  * ============================================================================= */
3109 NK_API float nk_slide_float(struct nk_context*, float min, float val, float max, float step);
3110 NK_API int nk_slide_int(struct nk_context*, int min, int val, int max, int step);
3111 NK_API int nk_slider_float(struct nk_context*, float min, float *val, float max, float step);
3112 NK_API int nk_slider_int(struct nk_context*, int min, int *val, int max, int step);
3113 /* =============================================================================
3114  *
3115  * PROGRESSBAR
3116  *
3117  * ============================================================================= */
3118 NK_API int nk_progress(struct nk_context*, nk_size *cur, nk_size max, int modifyable);
3119 NK_API nk_size nk_prog(struct nk_context*, nk_size cur, nk_size max, int modifyable);
3120 
3121 /* =============================================================================
3122  *
3123  * COLOR PICKER
3124  *
3125  * ============================================================================= */
3126 NK_API struct nk_colorf nk_color_picker(struct nk_context*, struct nk_colorf, enum nk_color_format);
3127 NK_API int nk_color_pick(struct nk_context*, struct nk_colorf*, enum nk_color_format);
3128 /* =============================================================================
3129  *
3130  * PROPERTIES
3131  *
3132  * =============================================================================
3188 // nk_clear(&ctx);
3203 */
3204 /*/// #### nk_property_int
3223 */
3224 NK_API void nk_property_int(struct nk_context*, const char *name, int min, int *val, int max, int step, float inc_per_pixel);
3225 /*/// #### nk_property_float
3244 */
3245 NK_API void nk_property_float(struct nk_context*, const char *name, float min, float *val, float max, float step, float inc_per_pixel);
3246 /*/// #### nk_property_double
3265 */
3266 NK_API void nk_property_double(struct nk_context*, const char *name, double min, double *val, double max, double step, float inc_per_pixel);
3267 /*/// #### nk_propertyi
3288 */
3289 NK_API int nk_propertyi(struct nk_context*, const char *name, int min, int val, int max, int step, float inc_per_pixel);
3290 /*/// #### nk_propertyf
3311 */
3312 NK_API float nk_propertyf(struct nk_context*, const char *name, float min, float val, float max, float step, float inc_per_pixel);
3313 /*/// #### nk_propertyd
3334 */
3335 NK_API double nk_propertyd(struct nk_context*, const char *name, double min, double val, double max, double step, float inc_per_pixel);
3336 /* =============================================================================
3337  *
3338  * TEXT EDIT
3339  *
3340  * ============================================================================= */
3355 };
3361 };
3363  NK_EDIT_ACTIVE = NK_FLAG(0), /* edit widget is currently being modified */
3364  NK_EDIT_INACTIVE = NK_FLAG(1), /* edit widget is not active and is not being modified */
3365  NK_EDIT_ACTIVATED = NK_FLAG(2), /* edit widget went from state inactive to state active */
3366  NK_EDIT_DEACTIVATED = NK_FLAG(3), /* edit widget went from state active to state inactive */
3367  NK_EDIT_COMMITED = NK_FLAG(4) /* edit widget has received an enter and lost focus */
3368 };
3369 NK_API nk_flags nk_edit_string(struct nk_context*, nk_flags, char *buffer, int *len, int max, nk_plugin_filter);
3372 NK_API void nk_edit_focus(struct nk_context*, nk_flags flags);
3373 NK_API void nk_edit_unfocus(struct nk_context*);
3374 /* =============================================================================
3375  *
3376  * CHART
3377  *
3378  * ============================================================================= */
3379 NK_API int nk_chart_begin(struct nk_context*, enum nk_chart_type, int num, float min, float max);
3380 NK_API int nk_chart_begin_colored(struct nk_context*, enum nk_chart_type, struct nk_color, struct nk_color active, int num, float min, float max);
3381 NK_API void nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type, int count, float min_value, float max_value);
3382 NK_API void nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type, struct nk_color, struct nk_color active, int count, float min_value, float max_value);
3383 NK_API nk_flags nk_chart_push(struct nk_context*, float);
3384 NK_API nk_flags nk_chart_push_slot(struct nk_context*, float, int);
3385 NK_API void nk_chart_end(struct nk_context*);
3386 NK_API void nk_plot(struct nk_context*, enum nk_chart_type, const float *values, int count, int offset);
3387 NK_API void nk_plot_function(struct nk_context*, enum nk_chart_type, void *userdata, float(*value_getter)(void* user, int index), int count, int offset);
3388 /* =============================================================================
3389  *
3390  * POPUP
3391  *
3392  * ============================================================================= */
3393 NK_API int nk_popup_begin(struct nk_context*, enum nk_popup_type, const char*, nk_flags, struct nk_rect bounds);
3394 NK_API void nk_popup_close(struct nk_context*);
3395 NK_API void nk_popup_end(struct nk_context*);
3396 /* =============================================================================
3397  *
3398  * COMBOBOX
3399  *
3400  * ============================================================================= */
3401 NK_API int nk_combo(struct nk_context*, const char **items, int count, int selected, int item_height, struct nk_vec2 size);
3402 NK_API int nk_combo_separator(struct nk_context*, const char *items_separated_by_separator, int separator, int selected, int count, int item_height, struct nk_vec2 size);
3403 NK_API int nk_combo_string(struct nk_context*, const char *items_separated_by_zeros, int selected, int count, int item_height, struct nk_vec2 size);
3404 NK_API int nk_combo_callback(struct nk_context*, void(*item_getter)(void*, int, const char**), void *userdata, int selected, int count, int item_height, struct nk_vec2 size);
3405 NK_API void nk_combobox(struct nk_context*, const char **items, int count, int *selected, int item_height, struct nk_vec2 size);
3406 NK_API void nk_combobox_string(struct nk_context*, const char *items_separated_by_zeros, int *selected, int count, int item_height, struct nk_vec2 size);
3407 NK_API void nk_combobox_separator(struct nk_context*, const char *items_separated_by_separator, int separator,int *selected, int count, int item_height, struct nk_vec2 size);
3408 NK_API void nk_combobox_callback(struct nk_context*, void(*item_getter)(void*, int, const char**), void*, int *selected, int count, int item_height, struct nk_vec2 size);
3409 /* =============================================================================
3410  *
3411  * ABSTRACT COMBOBOX
3412  *
3413  * ============================================================================= */
3414 NK_API int nk_combo_begin_text(struct nk_context*, const char *selected, int, struct nk_vec2 size);
3415 NK_API int nk_combo_begin_label(struct nk_context*, const char *selected, struct nk_vec2 size);
3416 NK_API int nk_combo_begin_color(struct nk_context*, struct nk_color color, struct nk_vec2 size);
3417 NK_API int nk_combo_begin_symbol(struct nk_context*, enum nk_symbol_type, struct nk_vec2 size);
3418 NK_API int nk_combo_begin_symbol_label(struct nk_context*, const char *selected, enum nk_symbol_type, struct nk_vec2 size);
3419 NK_API int nk_combo_begin_symbol_text(struct nk_context*, const char *selected, int, enum nk_symbol_type, struct nk_vec2 size);
3420 NK_API int nk_combo_begin_image(struct nk_context*, struct nk_image img, struct nk_vec2 size);
3421 NK_API int nk_combo_begin_image_label(struct nk_context*, const char *selected, struct nk_image, struct nk_vec2 size);
3422 NK_API int nk_combo_begin_image_text(struct nk_context*, const char *selected, int, struct nk_image, struct nk_vec2 size);
3423 NK_API int nk_combo_item_label(struct nk_context*, const char*, nk_flags alignment);
3424 NK_API int nk_combo_item_text(struct nk_context*, const char*,int, nk_flags alignment);
3425 NK_API int nk_combo_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
3426 NK_API int nk_combo_item_image_text(struct nk_context*, struct nk_image, const char*, int,nk_flags alignment);
3427 NK_API int nk_combo_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
3428 NK_API int nk_combo_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
3429 NK_API void nk_combo_close(struct nk_context*);
3430 NK_API void nk_combo_end(struct nk_context*);
3431 /* =============================================================================
3432  *
3433  * CONTEXTUAL
3434  *
3435  * ============================================================================= */
3436 NK_API int nk_contextual_begin(struct nk_context*, nk_flags, struct nk_vec2, struct nk_rect trigger_bounds);
3437 NK_API int nk_contextual_item_text(struct nk_context*, const char*, int,nk_flags align);
3438 NK_API int nk_contextual_item_label(struct nk_context*, const char*, nk_flags align);
3439 NK_API int nk_contextual_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
3440 NK_API int nk_contextual_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment);
3441 NK_API int nk_contextual_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
3442 NK_API int nk_contextual_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
3443 NK_API void nk_contextual_close(struct nk_context*);
3444 NK_API void nk_contextual_end(struct nk_context*);
3445 /* =============================================================================
3446  *
3447  * TOOLTIP
3448  *
3449  * ============================================================================= */
3450 NK_API void nk_tooltip(struct nk_context*, const char*);
3451 #ifdef NK_INCLUDE_STANDARD_VARARGS
3452 NK_API void nk_tooltipf(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, ...) NK_PRINTF_VARARG_FUNC(2);
3453 NK_API void nk_tooltipfv(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(2);
3454 #endif
3455 NK_API int nk_tooltip_begin(struct nk_context*, float width);
3456 NK_API void nk_tooltip_end(struct nk_context*);
3457 /* =============================================================================
3458  *
3459  * MENU
3460  *
3461  * ============================================================================= */
3462 NK_API void nk_menubar_begin(struct nk_context*);
3463 NK_API void nk_menubar_end(struct nk_context*);
3464 NK_API int nk_menu_begin_text(struct nk_context*, const char* title, int title_len, nk_flags align, struct nk_vec2 size);
3465 NK_API int nk_menu_begin_label(struct nk_context*, const char*, nk_flags align, struct nk_vec2 size);
3466 NK_API int nk_menu_begin_image(struct nk_context*, const char*, struct nk_image, struct nk_vec2 size);
3467 NK_API int nk_menu_begin_image_text(struct nk_context*, const char*, int,nk_flags align,struct nk_image, struct nk_vec2 size);
3468 NK_API int nk_menu_begin_image_label(struct nk_context*, const char*, nk_flags align,struct nk_image, struct nk_vec2 size);
3469 NK_API int nk_menu_begin_symbol(struct nk_context*, const char*, enum nk_symbol_type, struct nk_vec2 size);
3470 NK_API int nk_menu_begin_symbol_text(struct nk_context*, const char*, int,nk_flags align,enum nk_symbol_type, struct nk_vec2 size);
3471 NK_API int nk_menu_begin_symbol_label(struct nk_context*, const char*, nk_flags align,enum nk_symbol_type, struct nk_vec2 size);
3472 NK_API int nk_menu_item_text(struct nk_context*, const char*, int,nk_flags align);
3473 NK_API int nk_menu_item_label(struct nk_context*, const char*, nk_flags alignment);
3474 NK_API int nk_menu_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
3475 NK_API int nk_menu_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment);
3476 NK_API int nk_menu_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
3477 NK_API int nk_menu_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
3478 NK_API void nk_menu_close(struct nk_context*);
3479 NK_API void nk_menu_end(struct nk_context*);
3480 /* =============================================================================
3481  *
3482  * STYLE
3483  *
3484  * ============================================================================= */
3515 };
3525 };
3526 NK_API void nk_style_default(struct nk_context*);
3527 NK_API void nk_style_from_table(struct nk_context*, const struct nk_color*);
3528 NK_API void nk_style_load_cursor(struct nk_context*, enum nk_style_cursor, const struct nk_cursor*);
3529 NK_API void nk_style_load_all_cursors(struct nk_context*, struct nk_cursor*);
3531 NK_API void nk_style_set_font(struct nk_context*, const struct nk_user_font*);
3533 NK_API void nk_style_show_cursor(struct nk_context*);
3534 NK_API void nk_style_hide_cursor(struct nk_context*);
3535 
3536 NK_API int nk_style_push_font(struct nk_context*, const struct nk_user_font*);
3537 NK_API int nk_style_push_float(struct nk_context*, float*, float);
3538 NK_API int nk_style_push_vec2(struct nk_context*, struct nk_vec2*, struct nk_vec2);
3541 NK_API int nk_style_push_color(struct nk_context*, struct nk_color*, struct nk_color);
3542 
3543 NK_API int nk_style_pop_font(struct nk_context*);
3544 NK_API int nk_style_pop_float(struct nk_context*);
3545 NK_API int nk_style_pop_vec2(struct nk_context*);
3547 NK_API int nk_style_pop_flags(struct nk_context*);
3548 NK_API int nk_style_pop_color(struct nk_context*);
3549 /* =============================================================================
3550  *
3551  * COLOR
3552  *
3553  * ============================================================================= */
3554 NK_API struct nk_color nk_rgb(int r, int g, int b);
3555 NK_API struct nk_color nk_rgb_iv(const int *rgb);
3556 NK_API struct nk_color nk_rgb_bv(const nk_byte* rgb);
3557 NK_API struct nk_color nk_rgb_f(float r, float g, float b);
3558 NK_API struct nk_color nk_rgb_fv(const float *rgb);
3559 NK_API struct nk_color nk_rgb_cf(struct nk_colorf c);
3560 NK_API struct nk_color nk_rgb_hex(const char *rgb);
3561 
3562 NK_API struct nk_color nk_rgba(int r, int g, int b, int a);
3564 NK_API struct nk_color nk_rgba_iv(const int *rgba);
3565 NK_API struct nk_color nk_rgba_bv(const nk_byte *rgba);
3566 NK_API struct nk_color nk_rgba_f(float r, float g, float b, float a);
3567 NK_API struct nk_color nk_rgba_fv(const float *rgba);
3568 NK_API struct nk_color nk_rgba_cf(struct nk_colorf c);
3569 NK_API struct nk_color nk_rgba_hex(const char *rgb);
3570 
3571 NK_API struct nk_colorf nk_hsva_colorf(float h, float s, float v, float a);
3572 NK_API struct nk_colorf nk_hsva_colorfv(float *c);
3573 NK_API void nk_colorf_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_colorf in);
3574 NK_API void nk_colorf_hsva_fv(float *hsva, struct nk_colorf in);
3575 
3576 NK_API struct nk_color nk_hsv(int h, int s, int v);
3577 NK_API struct nk_color nk_hsv_iv(const int *hsv);
3578 NK_API struct nk_color nk_hsv_bv(const nk_byte *hsv);
3579 NK_API struct nk_color nk_hsv_f(float h, float s, float v);
3580 NK_API struct nk_color nk_hsv_fv(const float *hsv);
3581 
3582 NK_API struct nk_color nk_hsva(int h, int s, int v, int a);
3583 NK_API struct nk_color nk_hsva_iv(const int *hsva);
3584 NK_API struct nk_color nk_hsva_bv(const nk_byte *hsva);
3585 NK_API struct nk_color nk_hsva_f(float h, float s, float v, float a);
3586 NK_API struct nk_color nk_hsva_fv(const float *hsva);
3587 
3588 /* color (conversion nuklear --> user) */
3589 NK_API void nk_color_f(float *r, float *g, float *b, float *a, struct nk_color);
3590 NK_API void nk_color_fv(float *rgba_out, struct nk_color);
3591 NK_API struct nk_colorf nk_color_cf(struct nk_color);
3592 NK_API void nk_color_d(double *r, double *g, double *b, double *a, struct nk_color);
3593 NK_API void nk_color_dv(double *rgba_out, struct nk_color);
3594 
3596 NK_API void nk_color_hex_rgba(char *output, struct nk_color);
3597 NK_API void nk_color_hex_rgb(char *output, struct nk_color);
3598 
3599 NK_API void nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color);
3600 NK_API void nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color);
3601 NK_API void nk_color_hsv_iv(int *hsv_out, struct nk_color);
3602 NK_API void nk_color_hsv_bv(nk_byte *hsv_out, struct nk_color);
3603 NK_API void nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color);
3604 NK_API void nk_color_hsv_fv(float *hsv_out, struct nk_color);
3605 
3606 NK_API void nk_color_hsva_i(int *h, int *s, int *v, int *a, struct nk_color);
3607 NK_API void nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color);
3608 NK_API void nk_color_hsva_iv(int *hsva_out, struct nk_color);
3609 NK_API void nk_color_hsva_bv(nk_byte *hsva_out, struct nk_color);
3610 NK_API void nk_color_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_color);
3611 NK_API void nk_color_hsva_fv(float *hsva_out, struct nk_color);
3612 /* =============================================================================
3613  *
3614  * IMAGE
3615  *
3616  * ============================================================================= */
3620 NK_API struct nk_image nk_image_ptr(void*);
3621 NK_API struct nk_image nk_image_id(int);
3622 NK_API int nk_image_is_subimage(const struct nk_image* img);
3623 NK_API struct nk_image nk_subimage_ptr(void*, unsigned short w, unsigned short h, struct nk_rect sub_region);
3624 NK_API struct nk_image nk_subimage_id(int, unsigned short w, unsigned short h, struct nk_rect sub_region);
3625 NK_API struct nk_image nk_subimage_handle(nk_handle, unsigned short w, unsigned short h, struct nk_rect sub_region);
3626 /* =============================================================================
3627  *
3628  * MATH
3629  *
3630  * ============================================================================= */
3631 NK_API nk_hash nk_murmur_hash(const void *key, int len, nk_hash seed);
3632 NK_API void nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, float pad_x, float pad_y, enum nk_heading);
3633 
3634 NK_API struct nk_vec2 nk_vec2(float x, float y);
3635 NK_API struct nk_vec2 nk_vec2i(int x, int y);
3636 NK_API struct nk_vec2 nk_vec2v(const float *xy);
3637 NK_API struct nk_vec2 nk_vec2iv(const int *xy);
3638 
3639 NK_API struct nk_rect nk_get_null_rect(void);
3640 NK_API struct nk_rect nk_rect(float x, float y, float w, float h);
3641 NK_API struct nk_rect nk_recti(int x, int y, int w, int h);
3642 NK_API struct nk_rect nk_recta(struct nk_vec2 pos, struct nk_vec2 size);
3643 NK_API struct nk_rect nk_rectv(const float *xywh);
3644 NK_API struct nk_rect nk_rectiv(const int *xywh);
3645 NK_API struct nk_vec2 nk_rect_pos(struct nk_rect);
3646 NK_API struct nk_vec2 nk_rect_size(struct nk_rect);
3647 /* =============================================================================
3648  *
3649  * STRING
3650  *
3651  * ============================================================================= */
3652 NK_API int nk_strlen(const char *str);
3653 NK_API int nk_stricmp(const char *s1, const char *s2);
3654 NK_API int nk_stricmpn(const char *s1, const char *s2, int n);
3655 NK_API int nk_strtoi(const char *str, const char **endptr);
3656 NK_API float nk_strtof(const char *str, const char **endptr);
3657 NK_API double nk_strtod(const char *str, const char **endptr);
3658 NK_API int nk_strfilter(const char *text, const char *regexp);
3659 NK_API int nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score);
3660 NK_API int nk_strmatch_fuzzy_text(const char *txt, int txt_len, const char *pattern, int *out_score);
3661 /* =============================================================================
3662  *
3663  * UTF-8
3664  *
3665  * ============================================================================= */
3666 NK_API int nk_utf_decode(const char*, nk_rune*, int);
3667 NK_API int nk_utf_encode(nk_rune, char*, int);
3668 NK_API int nk_utf_len(const char*, int byte_len);
3669 NK_API const char* nk_utf_at(const char *buffer, int length, int index, nk_rune *unicode, int *len);
3670 /* ===============================================================
3671  *
3672  * FONT
3673  *
3674  * ===============================================================*/
3675 /* Font handling in this library was designed to be quite customizable and lets
3676  you decide what you want to use and what you want to provide. There are three
3677  different ways to use the font atlas. The first two will use your font
3678  handling scheme and only requires essential data to run nuklear. The next
3679  slightly more advanced features is font handling with vertex buffer output.
3680  Finally the most complex API wise is using nuklear's font baking API.
3681 
3682  1.) Using your own implementation without vertex buffer output
3683  --------------------------------------------------------------
3684  So first up the easiest way to do font handling is by just providing a
3685  `nk_user_font` struct which only requires the height in pixel of the used
3686  font and a callback to calculate the width of a string. This way of handling
3687  fonts is best fitted for using the normal draw shape command API where you
3688  do all the text drawing yourself and the library does not require any kind
3689  of deeper knowledge about which font handling mechanism you use.
3690  IMPORTANT: the `nk_user_font` pointer provided to nuklear has to persist
3691  over the complete life time! I know this sucks but it is currently the only
3692  way to switch between fonts.
3693 
3694  float your_text_width_calculation(nk_handle handle, float height, const char *text, int len)
3695  {
3696  your_font_type *type = handle.ptr;
3697  float text_width = ...;
3698  return text_width;
3699  }
3700 
3701  struct nk_user_font font;
3702  font.userdata.ptr = &your_font_class_or_struct;
3703  font.height = your_font_height;
3704  font.width = your_text_width_calculation;
3705 
3706  struct nk_context ctx;
3707  nk_init_default(&ctx, &font);
3708 
3709  2.) Using your own implementation with vertex buffer output
3710  --------------------------------------------------------------
3711  While the first approach works fine if you don't want to use the optional
3712  vertex buffer output it is not enough if you do. To get font handling working
3713  for these cases you have to provide two additional parameters inside the
3714  `nk_user_font`. First a texture atlas handle used to draw text as subimages
3715  of a bigger font atlas texture and a callback to query a character's glyph
3716  information (offset, size, ...). So it is still possible to provide your own
3717  font and use the vertex buffer output.
3718 
3719  float your_text_width_calculation(nk_handle handle, float height, const char *text, int len)
3720  {
3721  your_font_type *type = handle.ptr;
3722  float text_width = ...;
3723  return text_width;
3724  }
3725  void query_your_font_glyph(nk_handle handle, float font_height, struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint)
3726  {
3727  your_font_type *type = handle.ptr;
3728  glyph.width = ...;
3729  glyph.height = ...;
3730  glyph.xadvance = ...;
3731  glyph.uv[0].x = ...;
3732  glyph.uv[0].y = ...;
3733  glyph.uv[1].x = ...;
3734  glyph.uv[1].y = ...;
3735  glyph.offset.x = ...;
3736  glyph.offset.y = ...;
3737  }
3738 
3739  struct nk_user_font font;
3740  font.userdata.ptr = &your_font_class_or_struct;
3741  font.height = your_font_height;
3742  font.width = your_text_width_calculation;
3743  font.query = query_your_font_glyph;
3744  font.texture.id = your_font_texture;
3745 
3746  struct nk_context ctx;
3747  nk_init_default(&ctx, &font);
3748 
3749  3.) Nuklear font baker
3750  ------------------------------------
3751  The final approach if you do not have a font handling functionality or don't
3752  want to use it in this library is by using the optional font baker.
3753  The font baker APIs can be used to create a font plus font atlas texture
3754  and can be used with or without the vertex buffer output.
3755 
3756  It still uses the `nk_user_font` struct and the two different approaches
3757  previously stated still work. The font baker is not located inside
3758  `nk_context` like all other systems since it can be understood as more of
3759  an extension to nuklear and does not really depend on any `nk_context` state.
3760 
3761  Font baker need to be initialized first by one of the nk_font_atlas_init_xxx
3762  functions. If you don't care about memory just call the default version
3763  `nk_font_atlas_init_default` which will allocate all memory from the standard library.
3764  If you want to control memory allocation but you don't care if the allocated
3765  memory is temporary and therefore can be freed directly after the baking process
3766  is over or permanent you can call `nk_font_atlas_init`.
3767 
3768  After successfully initializing the font baker you can add Truetype(.ttf) fonts from
3769  different sources like memory or from file by calling one of the `nk_font_atlas_add_xxx`.
3770  functions. Adding font will permanently store each font, font config and ttf memory block(!)
3771  inside the font atlas and allows to reuse the font atlas. If you don't want to reuse
3772  the font baker by for example adding additional fonts you can call
3773  `nk_font_atlas_cleanup` after the baking process is over (after calling nk_font_atlas_end).
3774 
3775  As soon as you added all fonts you wanted you can now start the baking process
3776  for every selected glyph to image by calling `nk_font_atlas_bake`.
3777  The baking process returns image memory, width and height which can be used to
3778  either create your own image object or upload it to any graphics library.
3779  No matter which case you finally have to call `nk_font_atlas_end` which
3780  will free all temporary memory including the font atlas image so make sure
3781  you created our texture beforehand. `nk_font_atlas_end` requires a handle
3782  to your font texture or object and optionally fills a `struct nk_draw_null_texture`
3783  which can be used for the optional vertex output. If you don't want it just
3784  set the argument to `NULL`.
3785 
3786  At this point you are done and if you don't want to reuse the font atlas you
3787  can call `nk_font_atlas_cleanup` to free all truetype blobs and configuration
3788  memory. Finally if you don't use the font atlas and any of it's fonts anymore
3789  you need to call `nk_font_atlas_clear` to free all memory still being used.
3790 
3791  struct nk_font_atlas atlas;
3792  nk_font_atlas_init_default(&atlas);
3793  nk_font_atlas_begin(&atlas);
3794  nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, 0);
3795  nk_font *font2 = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font2.ttf", 16, 0);
3796  const void* img = nk_font_atlas_bake(&atlas, &img_width, &img_height, NK_FONT_ATLAS_RGBA32);
3797  nk_font_atlas_end(&atlas, nk_handle_id(texture), 0);
3798 
3799  struct nk_context ctx;
3800  nk_init_default(&ctx, &font->handle);
3801  while (1) {
3802 
3803  }
3804  nk_font_atlas_clear(&atlas);
3805 
3806  The font baker API is probably the most complex API inside this library and
3807  I would suggest reading some of my examples `example/` to get a grip on how
3808  to use the font atlas. There are a number of details I left out. For example
3809  how to merge fonts, configure a font with `nk_font_config` to use other languages,
3810  use another texture coordinate format and a lot more:
3811 
3812  struct nk_font_config cfg = nk_font_config(font_pixel_height);
3813  cfg.merge_mode = nk_false or nk_true;
3814  cfg.range = nk_font_korean_glyph_ranges();
3815  cfg.coord_type = NK_COORD_PIXEL;
3816  nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, &cfg);
3817 
3818 */
3819 struct nk_user_font_glyph;
3820 typedef float(*nk_text_width_f)(nk_handle, float h, const char*, int len);
3821 typedef void(*nk_query_font_glyph_f)(nk_handle handle, float font_height,
3822  struct nk_user_font_glyph *glyph,
3823  nk_rune codepoint, nk_rune next_codepoint);
3824 
3825 #if defined(NK_INCLUDE_VERTEX_BUFFER_OUTPUT) || defined(NK_INCLUDE_SOFTWARE_FONT)
3826 struct nk_user_font_glyph {
3827  struct nk_vec2 uv[2];
3828  /* texture coordinates */
3829  struct nk_vec2 offset;
3830  /* offset between top left and glyph */
3831  float width, height;
3832  /* size of the glyph */
3833  float xadvance;
3834  /* offset to the next glyph */
3835 };
3836 #endif
3837 
3840  /* user provided font handle */
3841  float height;
3842  /* max height of the font */
3844  /* font string width in pixel callback */
3845 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
3846  nk_query_font_glyph_f query;
3847  /* font glyph callback to query drawing info */
3848  nk_handle texture;
3849  /* texture handle to the used font atlas or texture */
3850 #endif
3851 };
3852 
3853 #ifdef NK_INCLUDE_FONT_BAKING
3854 enum nk_font_coord_type {
3855  NK_COORD_UV, /* texture coordinates inside font glyphs are clamped between 0-1 */
3856  NK_COORD_PIXEL /* texture coordinates inside font glyphs are in absolute pixel */
3857 };
3858 
3859 struct nk_font;
3860 struct nk_baked_font {
3861  float height;
3862  /* height of the font */
3863  float ascent, descent;
3864  /* font glyphs ascent and descent */
3865  nk_rune glyph_offset;
3866  /* glyph array offset inside the font glyph baking output array */
3867  nk_rune glyph_count;
3868  /* number of glyphs of this font inside the glyph baking array output */
3869  const nk_rune *ranges;
3870  /* font codepoint ranges as pairs of (from/to) and 0 as last element */
3871 };
3872 
3873 struct nk_font_config {
3874  struct nk_font_config *next;
3875  /* NOTE: only used internally */
3876  void *ttf_blob;
3877  /* pointer to loaded TTF file memory block.
3878  * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */
3879  nk_size ttf_size;
3880  /* size of the loaded TTF file memory block
3881  * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */
3882 
3883  unsigned char ttf_data_owned_by_atlas;
3884  /* used inside font atlas: default to: 0*/
3885  unsigned char merge_mode;
3886  /* merges this font into the last font */
3887  unsigned char pixel_snap;
3888  /* align every character to pixel boundary (if true set oversample (1,1)) */
3889  unsigned char oversample_v, oversample_h;
3890  /* rasterize at hight quality for sub-pixel position */
3891  unsigned char padding[3];
3892 
3893  float size;
3894  /* baked pixel height of the font */
3895  enum nk_font_coord_type coord_type;
3896  /* texture coordinate format with either pixel or UV coordinates */
3897  struct nk_vec2 spacing;
3898  /* extra pixel spacing between glyphs */
3899  const nk_rune *range;
3900  /* list of unicode ranges (2 values per range, zero terminated) */
3901  struct nk_baked_font *font;
3902  /* font to setup in the baking process: NOTE: not needed for font atlas */
3903  nk_rune fallback_glyph;
3904  /* fallback glyph to use if a given rune is not found */
3905  struct nk_font_config *n;
3906  struct nk_font_config *p;
3907 };
3908 
3909 struct nk_font_glyph {
3910  nk_rune codepoint;
3911  float xadvance;
3912  float x0, y0, x1, y1, w, h;
3913  float u0, v0, u1, v1;
3914 };
3915 
3916 struct nk_font {
3917  struct nk_font *next;
3918  struct nk_user_font handle;
3919  struct nk_baked_font info;
3920  float scale;
3921  struct nk_font_glyph *glyphs;
3922  const struct nk_font_glyph *fallback;
3923  nk_rune fallback_codepoint;
3924  nk_handle texture;
3925  struct nk_font_config *config;
3926 };
3927 
3928 enum nk_font_atlas_format {
3929  NK_FONT_ATLAS_ALPHA8,
3930  NK_FONT_ATLAS_RGBA32
3931 };
3932 
3933 struct nk_font_atlas {
3934  void *pixel;
3935  int tex_width;
3936  int tex_height;
3937 
3938  struct nk_allocator permanent;
3939  struct nk_allocator temporary;
3940 
3941  struct nk_recti custom;
3942  struct nk_cursor cursors[NK_CURSOR_COUNT];
3943 
3944  int glyph_count;
3945  struct nk_font_glyph *glyphs;
3946  struct nk_font *default_font;
3947  struct nk_font *fonts;
3948  struct nk_font_config *config;
3949  int font_num;
3950 };
3951 
3952 /* some language glyph codepoint ranges */
3953 NK_API const nk_rune *nk_font_default_glyph_ranges(void);
3954 NK_API const nk_rune *nk_font_chinese_glyph_ranges(void);
3955 NK_API const nk_rune *nk_font_cyrillic_glyph_ranges(void);
3956 NK_API const nk_rune *nk_font_korean_glyph_ranges(void);
3957 
3958 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
3959 NK_API void nk_font_atlas_init_default(struct nk_font_atlas*);
3960 #endif
3961 NK_API void nk_font_atlas_init(struct nk_font_atlas*, struct nk_allocator*);
3962 NK_API void nk_font_atlas_init_custom(struct nk_font_atlas*, struct nk_allocator *persistent, struct nk_allocator *transient);
3963 NK_API void nk_font_atlas_begin(struct nk_font_atlas*);
3964 NK_API struct nk_font_config nk_font_config(float pixel_height);
3965 NK_API struct nk_font *nk_font_atlas_add(struct nk_font_atlas*, const struct nk_font_config*);
3966 #ifdef NK_INCLUDE_DEFAULT_FONT
3967 NK_API struct nk_font* nk_font_atlas_add_default(struct nk_font_atlas*, float height, const struct nk_font_config*);
3968 #endif
3969 NK_API struct nk_font* nk_font_atlas_add_from_memory(struct nk_font_atlas *atlas, void *memory, nk_size size, float height, const struct nk_font_config *config);
3970 #ifdef NK_INCLUDE_STANDARD_IO
3971 NK_API struct nk_font* nk_font_atlas_add_from_file(struct nk_font_atlas *atlas, const char *file_path, float height, const struct nk_font_config*);
3972 #endif
3973 NK_API struct nk_font *nk_font_atlas_add_compressed(struct nk_font_atlas*, void *memory, nk_size size, float height, const struct nk_font_config*);
3974 NK_API struct nk_font* nk_font_atlas_add_compressed_base85(struct nk_font_atlas*, const char *data, float height, const struct nk_font_config *config);
3975 NK_API const void* nk_font_atlas_bake(struct nk_font_atlas*, int *width, int *height, enum nk_font_atlas_format);
3976 NK_API void nk_font_atlas_end(struct nk_font_atlas*, nk_handle tex, struct nk_draw_null_texture*);
3977 NK_API const struct nk_font_glyph* nk_font_find_glyph(struct nk_font*, nk_rune unicode);
3978 NK_API void nk_font_atlas_cleanup(struct nk_font_atlas *atlas);
3979 NK_API void nk_font_atlas_clear(struct nk_font_atlas*);
3980 
3981 #endif
3982 
3983 /* ==============================================================
3984  *
3985  * MEMORY BUFFER
3986  *
3987  * ===============================================================*/
3988 /* A basic (double)-buffer with linear allocation and resetting as only
3989  freeing policy. The buffer's main purpose is to control all memory management
3990  inside the GUI toolkit and still leave memory control as much as possible in
3991  the hand of the user while also making sure the library is easy to use if
3992  not as much control is needed.
3993  In general all memory inside this library can be provided from the user in
3994  three different ways.
3995 
3996  The first way and the one providing most control is by just passing a fixed
3997  size memory block. In this case all control lies in the hand of the user
3998  since he can exactly control where the memory comes from and how much memory
3999  the library should consume. Of course using the fixed size API removes the
4000  ability to automatically resize a buffer if not enough memory is provided so
4001  you have to take over the resizing. While being a fixed sized buffer sounds
4002  quite limiting, it is very effective in this library since the actual memory
4003  consumption is quite stable and has a fixed upper bound for a lot of cases.
4004 
4005  If you don't want to think about how much memory the library should allocate
4006  at all time or have a very dynamic UI with unpredictable memory consumption
4007  habits but still want control over memory allocation you can use the dynamic
4008  allocator based API. The allocator consists of two callbacks for allocating
4009  and freeing memory and optional userdata so you can plugin your own allocator.
4010 
4011  The final and easiest way can be used by defining
4012  NK_INCLUDE_DEFAULT_ALLOCATOR which uses the standard library memory
4013  allocation functions malloc and free and takes over complete control over
4014  memory in this library.
4015 */
4017  void *memory;
4018  unsigned int type;
4023 };
4024 
4028 };
4029 
4034 };
4035 
4037  int active;
4039 };
4040 
4041 struct nk_memory {void *ptr;nk_size size;};
4042 struct nk_buffer {
4044  /* buffer marker to free a buffer to a certain offset */
4046  /* allocator callback for dynamic buffers */
4048  /* memory management type */
4050  /* memory and size of the current memory block */
4052  /* growing factor for dynamic memory management */
4054  /* total amount of memory allocated */
4056  /* totally consumed memory given that enough memory is present */
4058  /* number of allocation calls */
4060  /* current size of the buffer */
4061 };
4062 
4063 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
4064 NK_API void nk_buffer_init_default(struct nk_buffer*);
4065 #endif
4066 NK_API void nk_buffer_init(struct nk_buffer*, const struct nk_allocator*, nk_size size);
4067 NK_API void nk_buffer_init_fixed(struct nk_buffer*, void *memory, nk_size size);
4068 NK_API void nk_buffer_info(struct nk_memory_status*, struct nk_buffer*);
4069 NK_API void nk_buffer_push(struct nk_buffer*, enum nk_buffer_allocation_type type, const void *memory, nk_size size, nk_size align);
4070 NK_API void nk_buffer_mark(struct nk_buffer*, enum nk_buffer_allocation_type type);
4072 NK_API void nk_buffer_clear(struct nk_buffer*);
4073 NK_API void nk_buffer_free(struct nk_buffer*);
4074 NK_API void *nk_buffer_memory(struct nk_buffer*);
4075 NK_API const void *nk_buffer_memory_const(const struct nk_buffer*);
4077 
4078 /* ==============================================================
4079  *
4080  * STRING
4081  *
4082  * ===============================================================*/
4083 /* Basic string buffer which is only used in context with the text editor
4084  * to manage and manipulate dynamic or fixed size string content. This is _NOT_
4085  * the default string handling method. The only instance you should have any contact
4086  * with this API is if you interact with an `nk_text_edit` object inside one of the
4087  * copy and paste functions and even there only for more advanced cases. */
4088 struct nk_str {
4090  int len; /* in codepoints/runes/glyphs */
4091 };
4092 
4093 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
4094 NK_API void nk_str_init_default(struct nk_str*);
4095 #endif
4096 NK_API void nk_str_init(struct nk_str*, const struct nk_allocator*, nk_size size);
4097 NK_API void nk_str_init_fixed(struct nk_str*, void *memory, nk_size size);
4098 NK_API void nk_str_clear(struct nk_str*);
4099 NK_API void nk_str_free(struct nk_str*);
4100 
4101 NK_API int nk_str_append_text_char(struct nk_str*, const char*, int);
4102 NK_API int nk_str_append_str_char(struct nk_str*, const char*);
4103 NK_API int nk_str_append_text_utf8(struct nk_str*, const char*, int);
4104 NK_API int nk_str_append_str_utf8(struct nk_str*, const char*);
4105 NK_API int nk_str_append_text_runes(struct nk_str*, const nk_rune*, int);
4106 NK_API int nk_str_append_str_runes(struct nk_str*, const nk_rune*);
4107 
4108 NK_API int nk_str_insert_at_char(struct nk_str*, int pos, const char*, int);
4109 NK_API int nk_str_insert_at_rune(struct nk_str*, int pos, const char*, int);
4110 
4111 NK_API int nk_str_insert_text_char(struct nk_str*, int pos, const char*, int);
4112 NK_API int nk_str_insert_str_char(struct nk_str*, int pos, const char*);
4113 NK_API int nk_str_insert_text_utf8(struct nk_str*, int pos, const char*, int);
4114 NK_API int nk_str_insert_str_utf8(struct nk_str*, int pos, const char*);
4115 NK_API int nk_str_insert_text_runes(struct nk_str*, int pos, const nk_rune*, int);
4116 NK_API int nk_str_insert_str_runes(struct nk_str*, int pos, const nk_rune*);
4117 
4118 NK_API void nk_str_remove_chars(struct nk_str*, int len);
4119 NK_API void nk_str_remove_runes(struct nk_str *str, int len);
4120 NK_API void nk_str_delete_chars(struct nk_str*, int pos, int len);
4121 NK_API void nk_str_delete_runes(struct nk_str*, int pos, int len);
4122 
4123 NK_API char *nk_str_at_char(struct nk_str*, int pos);
4124 NK_API char *nk_str_at_rune(struct nk_str*, int pos, nk_rune *unicode, int *len);
4125 NK_API nk_rune nk_str_rune_at(const struct nk_str*, int pos);
4126 NK_API const char *nk_str_at_char_const(const struct nk_str*, int pos);
4127 NK_API const char *nk_str_at_const(const struct nk_str*, int pos, nk_rune *unicode, int *len);
4128 
4129 NK_API char *nk_str_get(struct nk_str*);
4130 NK_API const char *nk_str_get_const(const struct nk_str*);
4131 NK_API int nk_str_len(struct nk_str*);
4132 NK_API int nk_str_len_char(struct nk_str*);
4133 
4134 /*===============================================================
4135  *
4136  * TEXT EDITOR
4137  *
4138  * ===============================================================*/
4139 /* Editing text in this library is handled by either `nk_edit_string` or
4140  * `nk_edit_buffer`. But like almost everything in this library there are multiple
4141  * ways of doing it and a balance between control and ease of use with memory
4142  * as well as functionality controlled by flags.
4143  *
4144  * This library generally allows three different levels of memory control:
4145  * First of is the most basic way of just providing a simple char array with
4146  * string length. This method is probably the easiest way of handling simple
4147  * user text input. Main upside is complete control over memory while the biggest
4148  * downside in comparison with the other two approaches is missing undo/redo.
4149  *
4150  * For UIs that require undo/redo the second way was created. It is based on
4151  * a fixed size nk_text_edit struct, which has an internal undo/redo stack.
4152  * This is mainly useful if you want something more like a text editor but don't want
4153  * to have a dynamically growing buffer.
4154  *
4155  * The final way is using a dynamically growing nk_text_edit struct, which
4156  * has both a default version if you don't care where memory comes from and an
4157  * allocator version if you do. While the text editor is quite powerful for its
4158  * complexity I would not recommend editing gigabytes of data with it.
4159  * It is rather designed for uses cases which make sense for a GUI library not for
4160  * an full blown text editor.
4161  */
4162 #ifndef NK_TEXTEDIT_UNDOSTATECOUNT
4163 #define NK_TEXTEDIT_UNDOSTATECOUNT 99
4164 #endif
4165 
4166 #ifndef NK_TEXTEDIT_UNDOCHARCOUNT
4167 #define NK_TEXTEDIT_UNDOCHARCOUNT 999
4168 #endif
4169 
4170 struct nk_text_edit;
4175 };
4176 
4178  int where;
4182 };
4183 
4187  short undo_point;
4188  short redo_point;
4191 };
4192 
4196 };
4197 
4202 };
4203 
4206  struct nk_str string;
4209 
4210  int cursor;
4213  unsigned char mode;
4214  unsigned char cursor_at_end_of_line;
4215  unsigned char initialized;
4216  unsigned char has_preferred_x;
4217  unsigned char single_line;
4218  unsigned char active;
4219  unsigned char padding1;
4222 };
4223 
4224 /* filter function */
4225 NK_API int nk_filter_default(const struct nk_text_edit*, nk_rune unicode);
4226 NK_API int nk_filter_ascii(const struct nk_text_edit*, nk_rune unicode);
4227 NK_API int nk_filter_float(const struct nk_text_edit*, nk_rune unicode);
4228 NK_API int nk_filter_decimal(const struct nk_text_edit*, nk_rune unicode);
4229 NK_API int nk_filter_hex(const struct nk_text_edit*, nk_rune unicode);
4230 NK_API int nk_filter_oct(const struct nk_text_edit*, nk_rune unicode);
4231 NK_API int nk_filter_binary(const struct nk_text_edit*, nk_rune unicode);
4232 
4233 /* text editor */
4234 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
4235 NK_API void nk_textedit_init_default(struct nk_text_edit*);
4236 #endif
4237 NK_API void nk_textedit_init(struct nk_text_edit*, struct nk_allocator*, nk_size size);
4238 NK_API void nk_textedit_init_fixed(struct nk_text_edit*, void *memory, nk_size size);
4239 NK_API void nk_textedit_free(struct nk_text_edit*);
4240 NK_API void nk_textedit_text(struct nk_text_edit*, const char*, int total_len);
4241 NK_API void nk_textedit_delete(struct nk_text_edit*, int where, int len);
4244 NK_API int nk_textedit_cut(struct nk_text_edit*);
4245 NK_API int nk_textedit_paste(struct nk_text_edit*, char const*, int len);
4246 NK_API void nk_textedit_undo(struct nk_text_edit*);
4247 NK_API void nk_textedit_redo(struct nk_text_edit*);
4248 
4249 /* ===============================================================
4250  *
4251  * DRAWING
4252  *
4253  * ===============================================================*/
4254 /* This library was designed to be render backend agnostic so it does
4255  not draw anything to screen. Instead all drawn shapes, widgets
4256  are made of, are buffered into memory and make up a command queue.
4257  Each frame therefore fills the command buffer with draw commands
4258  that then need to be executed by the user and his own render backend.
4259  After that the command buffer needs to be cleared and a new frame can be
4260  started. It is probably important to note that the command buffer is the main
4261  drawing API and the optional vertex buffer API only takes this format and
4262  converts it into a hardware accessible format.
4263 
4264  To use the command queue to draw your own widgets you can access the
4265  command buffer of each window by calling `nk_window_get_canvas` after
4266  previously having called `nk_begin`:
4267 
4268  void draw_red_rectangle_widget(struct nk_context *ctx)
4269  {
4270  struct nk_command_buffer *canvas;
4271  struct nk_input *input = &ctx->input;
4272  canvas = nk_window_get_canvas(ctx);
4273 
4274  struct nk_rect space;
4275  enum nk_widget_layout_states state;
4276  state = nk_widget(&space, ctx);
4277  if (!state) return;
4278 
4279  if (state != NK_WIDGET_ROM)
4280  update_your_widget_by_user_input(...);
4281  nk_fill_rect(canvas, space, 0, nk_rgb(255,0,0));
4282  }
4283 
4284  if (nk_begin(...)) {
4285  nk_layout_row_dynamic(ctx, 25, 1);
4286  draw_red_rectangle_widget(ctx);
4287  }
4288  nk_end(..)
4289 
4290  Important to know if you want to create your own widgets is the `nk_widget`
4291  call. It allocates space on the panel reserved for this widget to be used,
4292  but also returns the state of the widget space. If your widget is not seen and does
4293  not have to be updated it is '0' and you can just return. If it only has
4294  to be drawn the state will be `NK_WIDGET_ROM` otherwise you can do both
4295  update and draw your widget. The reason for separating is to only draw and
4296  update what is actually necessary which is crucial for performance.
4297 */
4318 };
4319 
4320 /* command base and header of every command inside the buffer */
4321 struct nk_command {
4324 #ifdef NK_INCLUDE_COMMAND_USERDATA
4325  nk_handle userdata;
4326 #endif
4327 };
4328 
4331  short x, y;
4332  unsigned short w, h;
4333 };
4334 
4337  unsigned short line_thickness;
4338  struct nk_vec2i begin;
4339  struct nk_vec2i end;
4340  struct nk_color color;
4341 };
4342 
4345  unsigned short line_thickness;
4346  struct nk_vec2i begin;
4347  struct nk_vec2i end;
4348  struct nk_vec2i ctrl[2];
4349  struct nk_color color;
4350 };
4351 
4354  unsigned short rounding;
4355  unsigned short line_thickness;
4356  short x, y;
4357  unsigned short w, h;
4358  struct nk_color color;
4359 };
4360 
4363  unsigned short rounding;
4364  short x, y;
4365  unsigned short w, h;
4366  struct nk_color color;
4367 };
4368 
4371  short x, y;
4372  unsigned short w, h;
4373  struct nk_color left;
4374  struct nk_color top;
4376  struct nk_color right;
4377 };
4378 
4381  unsigned short line_thickness;
4382  struct nk_vec2i a;
4383  struct nk_vec2i b;
4384  struct nk_vec2i c;
4385  struct nk_color color;
4386 };
4387 
4390  struct nk_vec2i a;
4391  struct nk_vec2i b;
4392  struct nk_vec2i c;
4393  struct nk_color color;
4394 };
4395 
4398  short x, y;
4399  unsigned short line_thickness;
4400  unsigned short w, h;
4401  struct nk_color color;
4402 };
4403 
4406  short x, y;
4407  unsigned short w, h;
4408  struct nk_color color;
4409 };
4410 
4413  short cx, cy;
4414  unsigned short r;
4415  unsigned short line_thickness;
4416  float a[2];
4417  struct nk_color color;
4418 };
4419 
4422  short cx, cy;
4423  unsigned short r;
4424  float a[2];
4425  struct nk_color color;
4426 };
4427 
4430  struct nk_color color;
4431  unsigned short line_thickness;
4432  unsigned short point_count;
4433  struct nk_vec2i points[1];
4434 };
4435 
4438  struct nk_color color;
4439  unsigned short point_count;
4440  struct nk_vec2i points[1];
4441 };
4442 
4445  struct nk_color color;
4446  unsigned short line_thickness;
4447  unsigned short point_count;
4448  struct nk_vec2i points[1];
4449 };
4450 
4453  short x, y;
4454  unsigned short w, h;
4455  struct nk_image img;
4456  struct nk_color col;
4457 };
4458 
4459 typedef void (*nk_command_custom_callback)(void *canvas, short x,short y,
4460  unsigned short w, unsigned short h, nk_handle callback_data);
4463  short x, y;
4464  unsigned short w, h;
4467 };
4468 
4471  const struct nk_user_font *font;
4474  short x, y;
4475  unsigned short w, h;
4476  float height;
4477  int length;
4478  char string[1];
4479 };
4480 
4484 };
4485 
4487  struct nk_buffer *base;
4488  struct nk_rect clip;
4492 };
4493 
4494 /* shape outlines */
4495 NK_API void nk_stroke_line(struct nk_command_buffer *b, float x0, float y0, float x1, float y1, float line_thickness, struct nk_color);
4496 NK_API void nk_stroke_curve(struct nk_command_buffer*, float, float, float, float, float, float, float, float, float line_thickness, struct nk_color);
4497 NK_API void nk_stroke_rect(struct nk_command_buffer*, struct nk_rect, float rounding, float line_thickness, struct nk_color);
4498 NK_API void nk_stroke_circle(struct nk_command_buffer*, struct nk_rect, float line_thickness, struct nk_color);
4499 NK_API void nk_stroke_arc(struct nk_command_buffer*, float cx, float cy, float radius, float a_min, float a_max, float line_thickness, struct nk_color);
4500 NK_API void nk_stroke_triangle(struct nk_command_buffer*, float, float, float, float, float, float, float line_thichness, struct nk_color);
4501 NK_API void nk_stroke_polyline(struct nk_command_buffer*, float *points, int point_count, float line_thickness, struct nk_color col);
4502 NK_API void nk_stroke_polygon(struct nk_command_buffer*, float*, int point_count, float line_thickness, struct nk_color);
4503 
4504 /* filled shades */
4505 NK_API void nk_fill_rect(struct nk_command_buffer*, struct nk_rect, float rounding, struct nk_color);
4506 NK_API void nk_fill_rect_multi_color(struct nk_command_buffer*, struct nk_rect, struct nk_color left, struct nk_color top, struct nk_color right, struct nk_color bottom);
4507 NK_API void nk_fill_circle(struct nk_command_buffer*, struct nk_rect, struct nk_color);
4508 NK_API void nk_fill_arc(struct nk_command_buffer*, float cx, float cy, float radius, float a_min, float a_max, struct nk_color);
4509 NK_API void nk_fill_triangle(struct nk_command_buffer*, float x0, float y0, float x1, float y1, float x2, float y2, struct nk_color);
4510 NK_API void nk_fill_polygon(struct nk_command_buffer*, float*, int point_count, struct nk_color);
4511 
4512 /* misc */
4513 NK_API void nk_draw_image(struct nk_command_buffer*, struct nk_rect, const struct nk_image*, struct nk_color);
4514 NK_API void nk_draw_text(struct nk_command_buffer*, struct nk_rect, const char *text, int len, const struct nk_user_font*, struct nk_color, struct nk_color);
4515 NK_API void nk_push_scissor(struct nk_command_buffer*, struct nk_rect);
4517 
4518 /* ===============================================================
4519  *
4520  * INPUT
4521  *
4522  * ===============================================================*/
4524  int down;
4525  unsigned int clicked;
4527 };
4528 struct nk_mouse {
4530  struct nk_vec2 pos;
4531  struct nk_vec2 prev;
4532  struct nk_vec2 delta;
4534  unsigned char grab;
4535  unsigned char grabbed;
4536  unsigned char ungrab;
4537 };
4538 
4539 struct nk_key {
4540  int down;
4541  unsigned int clicked;
4542 };
4543 struct nk_keyboard {
4547 };
4548 
4549 struct nk_input {
4551  struct nk_mouse mouse;
4552 };
4553 
4554 NK_API int nk_input_has_mouse_click(const struct nk_input*, enum nk_buttons);
4555 NK_API int nk_input_has_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect);
4556 NK_API int nk_input_has_mouse_click_down_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect, int down);
4557 NK_API int nk_input_is_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect);
4558 NK_API int nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, struct nk_rect b, int down);
4559 NK_API int nk_input_any_mouse_click_in_rect(const struct nk_input*, struct nk_rect);
4560 NK_API int nk_input_is_mouse_prev_hovering_rect(const struct nk_input*, struct nk_rect);
4561 NK_API int nk_input_is_mouse_hovering_rect(const struct nk_input*, struct nk_rect);
4562 NK_API int nk_input_mouse_clicked(const struct nk_input*, enum nk_buttons, struct nk_rect);
4563 NK_API int nk_input_is_mouse_down(const struct nk_input*, enum nk_buttons);
4564 NK_API int nk_input_is_mouse_pressed(const struct nk_input*, enum nk_buttons);
4565 NK_API int nk_input_is_mouse_released(const struct nk_input*, enum nk_buttons);
4566 NK_API int nk_input_is_key_pressed(const struct nk_input*, enum nk_keys);
4567 NK_API int nk_input_is_key_released(const struct nk_input*, enum nk_keys);
4568 NK_API int nk_input_is_key_down(const struct nk_input*, enum nk_keys);
4569 
4570 /* ===============================================================
4571  *
4572  * DRAW LIST
4573  *
4574  * ===============================================================*/
4575 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
4576 /* The optional vertex buffer draw list provides a 2D drawing context
4577  with antialiasing functionality which takes basic filled or outlined shapes
4578  or a path and outputs vertexes, elements and draw commands.
4579  The actual draw list API is not required to be used directly while using this
4580  library since converting the default library draw command output is done by
4581  just calling `nk_convert` but I decided to still make this library accessible
4582  since it can be useful.
4583 
4584  The draw list is based on a path buffering and polygon and polyline
4585  rendering API which allows a lot of ways to draw 2D content to screen.
4586  In fact it is probably more powerful than needed but allows even more crazy
4587  things than this library provides by default.
4588 */
4589 typedef nk_ushort nk_draw_index;
4590 enum nk_draw_list_stroke {
4591  NK_STROKE_OPEN = nk_false,
4592  /* build up path has no connection back to the beginning */
4593  NK_STROKE_CLOSED = nk_true
4594  /* build up path has a connection back to the beginning */
4595 };
4596 
4597 enum nk_draw_vertex_layout_attribute {
4598  NK_VERTEX_POSITION,
4599  NK_VERTEX_COLOR,
4600  NK_VERTEX_TEXCOORD,
4601  NK_VERTEX_ATTRIBUTE_COUNT
4602 };
4603 
4604 enum nk_draw_vertex_layout_format {
4605  NK_FORMAT_SCHAR,
4606  NK_FORMAT_SSHORT,
4607  NK_FORMAT_SINT,
4608  NK_FORMAT_UCHAR,
4609  NK_FORMAT_USHORT,
4610  NK_FORMAT_UINT,
4611  NK_FORMAT_FLOAT,
4612  NK_FORMAT_DOUBLE,
4613 
4614 NK_FORMAT_COLOR_BEGIN,
4615  NK_FORMAT_R8G8B8 = NK_FORMAT_COLOR_BEGIN,
4616  NK_FORMAT_R16G15B16,
4617  NK_FORMAT_R32G32B32,
4618 
4619  NK_FORMAT_R8G8B8A8,
4620  NK_FORMAT_B8G8R8A8,
4621  NK_FORMAT_R16G15B16A16,
4622  NK_FORMAT_R32G32B32A32,
4623  NK_FORMAT_R32G32B32A32_FLOAT,
4624  NK_FORMAT_R32G32B32A32_DOUBLE,
4625 
4626  NK_FORMAT_RGB32,
4627  NK_FORMAT_RGBA32,
4628 NK_FORMAT_COLOR_END = NK_FORMAT_RGBA32,
4629  NK_FORMAT_COUNT
4630 };
4631 
4632 #define NK_VERTEX_LAYOUT_END NK_VERTEX_ATTRIBUTE_COUNT,NK_FORMAT_COUNT,0
4633 struct nk_draw_vertex_layout_element {
4634  enum nk_draw_vertex_layout_attribute attribute;
4635  enum nk_draw_vertex_layout_format format;
4636  nk_size offset;
4637 };
4638 
4639 struct nk_draw_command {
4640  unsigned int elem_count;
4641  /* number of elements in the current draw batch */
4642  struct nk_rect clip_rect;
4643  /* current screen clipping rectangle */
4644  nk_handle texture;
4645  /* current texture to set */
4646 #ifdef NK_INCLUDE_COMMAND_USERDATA
4647  nk_handle userdata;
4648 #endif
4649 };
4650 
4651 struct nk_draw_list {
4652  struct nk_rect clip_rect;
4653  struct nk_vec2 circle_vtx[12];
4654  struct nk_convert_config config;
4655 
4656  struct nk_buffer *buffer;
4657  struct nk_buffer *vertices;
4658  struct nk_buffer *elements;
4659 
4660  unsigned int element_count;
4661  unsigned int vertex_count;
4662  unsigned int cmd_count;
4663  nk_size cmd_offset;
4664 
4665  unsigned int path_count;
4666  unsigned int path_offset;
4667 
4668  enum nk_anti_aliasing line_AA;
4669  enum nk_anti_aliasing shape_AA;
4670 
4671 #ifdef NK_INCLUDE_COMMAND_USERDATA
4672  nk_handle userdata;
4673 #endif
4674 };
4675 
4676 /* draw list */
4677 NK_API void nk_draw_list_init(struct nk_draw_list*);
4678 NK_API void nk_draw_list_setup(struct nk_draw_list*, const struct nk_convert_config*, struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements, enum nk_anti_aliasing line_aa,enum nk_anti_aliasing shape_aa);
4679 
4680 /* drawing */
4681 #define nk_draw_list_foreach(cmd, can, b) for((cmd)=nk__draw_list_begin(can, b); (cmd)!=0; (cmd)=nk__draw_list_next(cmd, b, can))
4682 NK_API const struct nk_draw_command* nk__draw_list_begin(const struct nk_draw_list*, const struct nk_buffer*);
4683 NK_API const struct nk_draw_command* nk__draw_list_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_draw_list*);
4684 NK_API const struct nk_draw_command* nk__draw_list_end(const struct nk_draw_list*, const struct nk_buffer*);
4685 
4686 /* path */
4687 NK_API void nk_draw_list_path_clear(struct nk_draw_list*);
4688 NK_API void nk_draw_list_path_line_to(struct nk_draw_list*, struct nk_vec2 pos);
4689 NK_API void nk_draw_list_path_arc_to_fast(struct nk_draw_list*, struct nk_vec2 center, float radius, int a_min, int a_max);
4690 NK_API void nk_draw_list_path_arc_to(struct nk_draw_list*, struct nk_vec2 center, float radius, float a_min, float a_max, unsigned int segments);
4691 NK_API void nk_draw_list_path_rect_to(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, float rounding);
4692 NK_API void nk_draw_list_path_curve_to(struct nk_draw_list*, struct nk_vec2 p2, struct nk_vec2 p3, struct nk_vec2 p4, unsigned int num_segments);
4693 NK_API void nk_draw_list_path_fill(struct nk_draw_list*, struct nk_color);
4694 NK_API void nk_draw_list_path_stroke(struct nk_draw_list*, struct nk_color, enum nk_draw_list_stroke closed, float thickness);
4695 
4696 /* stroke */
4697 NK_API void nk_draw_list_stroke_line(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, struct nk_color, float thickness);
4698 NK_API void nk_draw_list_stroke_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding, float thickness);
4699 NK_API void nk_draw_list_stroke_triangle(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, struct nk_vec2 c, struct nk_color, float thickness);
4700 NK_API void nk_draw_list_stroke_circle(struct nk_draw_list*, struct nk_vec2 center, float radius, struct nk_color, unsigned int segs, float thickness);
4701 NK_API void nk_draw_list_stroke_curve(struct nk_draw_list*, struct nk_vec2 p0, struct nk_vec2 cp0, struct nk_vec2 cp1, struct nk_vec2 p1, struct nk_color, unsigned int segments, float thickness);
4702 NK_API void nk_draw_list_stroke_poly_line(struct nk_draw_list*, const struct nk_vec2 *pnts, const unsigned int cnt, struct nk_color, enum nk_draw_list_stroke, float thickness, enum nk_anti_aliasing);
4703 
4704 /* fill */
4705 NK_API void nk_draw_list_fill_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding);
4706 NK_API void nk_draw_list_fill_rect_multi_color(struct nk_draw_list*, struct nk_rect rect, struct nk_color left, struct nk_color top, struct nk_color right, struct nk_color bottom);
4707 NK_API void nk_draw_list_fill_triangle(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, struct nk_vec2 c, struct nk_color);
4708 NK_API void nk_draw_list_fill_circle(struct nk_draw_list*, struct nk_vec2 center, float radius, struct nk_color col, unsigned int segs);
4709 NK_API void nk_draw_list_fill_poly_convex(struct nk_draw_list*, const struct nk_vec2 *points, const unsigned int count, struct nk_color, enum nk_anti_aliasing);
4710 
4711 /* misc */
4712 NK_API void nk_draw_list_add_image(struct nk_draw_list*, struct nk_image texture, struct nk_rect rect, struct nk_color);
4713 NK_API void nk_draw_list_add_text(struct nk_draw_list*, const struct nk_user_font*, struct nk_rect, const char *text, int len, float font_height, struct nk_color);
4714 #ifdef NK_INCLUDE_COMMAND_USERDATA
4715 NK_API void nk_draw_list_push_userdata(struct nk_draw_list*, nk_handle userdata);
4716 #endif
4717 
4718 #endif
4719 
4720 /* ===============================================================
4721  *
4722  * GUI
4723  *
4724  * ===============================================================*/
4728 };
4729 
4731  struct nk_image image;
4732  struct nk_color color;
4733 };
4734 
4738 };
4739 
4741  struct nk_color color;
4743 };
4744 
4746  /* background */
4751 
4752  /* text */
4758 
4759  /* properties */
4760  float border;
4761  float rounding;
4765 
4766  /* optional user callbacks */
4770 };
4771 
4773  /* background */
4778 
4779  /* cursor */
4782 
4783  /* text */
4789 
4790  /* properties */
4793  float spacing;
4794  float border;
4795 
4796  /* optional user callbacks */
4800 };
4801 
4803  /* background (inactive) */
4807 
4808  /* background (active) */
4812 
4813  /* text color (inactive) */
4817 
4818  /* text color (active) */
4824 
4825  /* properties */
4826  float rounding;
4830 
4831  /* optional user callbacks */
4835 };
4836 
4838  /* background */
4843 
4844  /* background bar */
4849 
4850  /* cursor */
4854 
4855  /* properties */
4856  float border;
4857  float rounding;
4858  float bar_height;
4862 
4863  /* optional buttons */
4869 
4870  /* optional user callbacks */
4874 };
4875 
4877  /* background */
4882 
4883  /* cursor */
4888 
4889  /* properties */
4890  float rounding;
4891  float border;
4895 
4896  /* optional user callbacks */
4900 };
4901 
4903  /* background */
4908 
4909  /* cursor */
4914 
4915  /* properties */
4916  float border;
4917  float rounding;
4921 
4922  /* optional buttons */
4928 
4929  /* optional user callbacks */
4933 };
4934 
4936  /* background */
4942 
4943  /* cursor */
4948 
4949  /* text (unselected) */
4953 
4954  /* text (selected) */
4959 
4960  /* properties */
4961  float border;
4962  float rounding;
4967 };
4968 
4970  /* background */
4975 
4976  /* text */
4980 
4981  /* symbols */
4984 
4985  /* properties */
4986  float border;
4987  float rounding;
4989 
4993 
4994  /* optional user callbacks */
4998 };
4999 
5001  /* colors */
5005  struct nk_color color;
5006 
5007  /* properties */
5008  float border;
5009  float rounding;
5011 };
5012 
5014  /* background */
5019 
5020  /* label */
5024 
5025  /* symbol */
5029 
5030  /* button */
5035 
5036  /* properties */
5037  float border;
5038  float rounding;
5042 };
5043 
5045  /* background */
5048  struct nk_color text;
5049 
5050  /* button */
5057 
5058  /* properties */
5059  float border;
5060  float rounding;
5061  float indent;
5064 };
5065 
5069 };
5071  /* background */
5075 
5076  /* button */
5082 
5083  /* title */
5087 
5088  /* properties */
5093 };
5094 
5099 
5108 
5109  float border;
5117 
5118  float rounding;
5122 
5130 };
5131 
5132 struct nk_style {
5133  const struct nk_user_font *font;
5135  const struct nk_cursor *cursor_active;
5138 
5156 };
5157 
5161 
5162 /*==============================================================
5163  * PANEL
5164  * =============================================================*/
5165 #ifndef NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS
5166 #define NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS 16
5167 #endif
5168 #ifndef NK_CHART_MAX_SLOT
5169 #define NK_CHART_MAX_SLOT 4
5170 #endif
5171 
5181 };
5186 };
5187 
5190  struct nk_color color;
5192  float min, max, range;
5193  int count;
5194  struct nk_vec2 last;
5195  int index;
5196 };
5197 
5198 struct nk_chart {
5199  int slot;
5200  float x, y, w, h;
5202 };
5203 
5215 };
5218  int index;
5219  float height;
5220  float min_height;
5221  int columns;
5222  const float *ratio;
5223  float item_width;
5226  float filled;
5227  struct nk_rect item;
5230 };
5231 
5237  int active;
5238 };
5239 
5241  float x, y, w, h;
5243 };
5244 
5245 struct nk_panel {
5248  struct nk_rect bounds;
5251  float at_x, at_y, max_x;
5254  float border;
5255  unsigned int has_scrolling;
5256  struct nk_rect clip;
5259  struct nk_chart chart;
5261  struct nk_panel *parent;
5262 };
5263 
5264 /*==============================================================
5265  * WINDOW
5266  * =============================================================*/
5267 #ifndef NK_WINDOW_MAX_NAME
5268 #define NK_WINDOW_MAX_NAME 64
5269 #endif
5270 
5271 struct nk_table;
5275  /* special window type growing up in height while being filled to a certain maximum height */
5277  /* sets window widgets into a read only mode and does not allow input changes */
5279  /* prevents all interaction caused by input to either window or widgets inside */
5281  /* Hides window and stops any window interaction and drawing */
5283  /* Directly closes and frees the window at the end of the frame */
5285  /* marks the window as minimized */
5287  /* Removes read only mode at the end of the window */
5288 };
5289 
5291  struct nk_window *win;
5295  int active;
5296  unsigned combo_count;
5297  unsigned con_count, con_old;
5298  unsigned active_con;
5299  struct nk_rect header;
5300 };
5301 
5304  unsigned int seq;
5305  unsigned int old;
5306  int active, prev;
5307  int cursor;
5309  int sel_end;
5311  unsigned char mode;
5312  unsigned char single_line;
5313 };
5314 
5316  int active, prev;
5318  int length;
5319  int cursor;
5323  unsigned int seq;
5324  unsigned int old;
5325  int state;
5326 };
5327 
5328 struct nk_window {
5329  unsigned int seq;
5333 
5334  struct nk_rect bounds;
5337  struct nk_panel *layout;
5339 
5340  /* persistent widget state */
5344  unsigned int scrolled;
5345 
5346  struct nk_table *tables;
5347  unsigned int table_count;
5348 
5349  /* window list hooks */
5350  struct nk_window *next;
5351  struct nk_window *prev;
5353 };
5354 
5355 /*==============================================================
5356  * STACK
5357  * =============================================================*/
5358 /* The style modifier stack can be used to temporarily change a
5359  * property inside `nk_style`. For example if you want a special
5360  * red button you can temporarily push the old button color onto a stack
5361  * draw the button with a red color and then you just pop the old color
5362  * back from the stack:
5363  *
5364  * nk_style_push_style_item(ctx, &ctx->style.button.normal, nk_style_item_color(nk_rgb(255,0,0)));
5365  * nk_style_push_style_item(ctx, &ctx->style.button.hover, nk_style_item_color(nk_rgb(255,0,0)));
5366  * nk_style_push_style_item(ctx, &ctx->style.button.active, nk_style_item_color(nk_rgb(255,0,0)));
5367  * nk_style_push_vec2(ctx, &cx->style.button.padding, nk_vec2(2,2));
5368  *
5369  * nk_button(...);
5370  *
5371  * nk_style_pop_style_item(ctx);
5372  * nk_style_pop_style_item(ctx);
5373  * nk_style_pop_style_item(ctx);
5374  * nk_style_pop_vec2(ctx);
5375  *
5376  * Nuklear has a stack for style_items, float properties, vector properties,
5377  * flags, colors, fonts and for button_behavior. Each has it's own fixed size stack
5378  * which can be changed at compile time.
5379  */
5380 #ifndef NK_BUTTON_BEHAVIOR_STACK_SIZE
5381 #define NK_BUTTON_BEHAVIOR_STACK_SIZE 8
5382 #endif
5383 
5384 #ifndef NK_FONT_STACK_SIZE
5385 #define NK_FONT_STACK_SIZE 8
5386 #endif
5387 
5388 #ifndef NK_STYLE_ITEM_STACK_SIZE
5389 #define NK_STYLE_ITEM_STACK_SIZE 16
5390 #endif
5391 
5392 #ifndef NK_FLOAT_STACK_SIZE
5393 #define NK_FLOAT_STACK_SIZE 32
5394 #endif
5395 
5396 #ifndef NK_VECTOR_STACK_SIZE
5397 #define NK_VECTOR_STACK_SIZE 16
5398 #endif
5399 
5400 #ifndef NK_FLAGS_STACK_SIZE
5401 #define NK_FLAGS_STACK_SIZE 32
5402 #endif
5403 
5404 #ifndef NK_COLOR_STACK_SIZE
5405 #define NK_COLOR_STACK_SIZE 32
5406 #endif
5407 
5408 #define NK_CONFIGURATION_STACK_TYPE(prefix, name, type)\
5409  struct nk_config_stack_##name##_element {\
5410  prefix##_##type *address;\
5411  prefix##_##type old_value;\
5412  }
5413 #define NK_CONFIG_STACK(type,size)\
5414  struct nk_config_stack_##type {\
5415  int head;\
5416  struct nk_config_stack_##type##_element elements[size];\
5417  }
5418 
5419 #define nk_float float
5420 NK_CONFIGURATION_STACK_TYPE(struct nk, style_item, style_item);
5421 NK_CONFIGURATION_STACK_TYPE(nk ,float, float);
5422 NK_CONFIGURATION_STACK_TYPE(struct nk, vec2, vec2);
5424 NK_CONFIGURATION_STACK_TYPE(struct nk, color, color);
5425 NK_CONFIGURATION_STACK_TYPE(const struct nk, user_font, user_font*);
5426 NK_CONFIGURATION_STACK_TYPE(enum nk, button_behavior, button_behavior);
5427 
5435 
5437  struct nk_config_stack_style_item style_items;
5438  struct nk_config_stack_float floats;
5439  struct nk_config_stack_vec2 vectors;
5440  struct nk_config_stack_flags flags;
5441  struct nk_config_stack_color colors;
5442  struct nk_config_stack_user_font fonts;
5443  struct nk_config_stack_button_behavior button_behaviors;
5444 };
5445 
5446 /*==============================================================
5447  * CONTEXT
5448  * =============================================================*/
5449 #define NK_VALUE_PAGE_CAPACITY \
5450  (((NK_MAX(sizeof(struct nk_window),sizeof(struct nk_panel)) / sizeof(nk_uint))) / 2)
5451 
5452 struct nk_table {
5453  unsigned int seq;
5454  unsigned int size;
5457  struct nk_table *next, *prev;
5458 };
5459 
5461  struct nk_table tbl;
5462  struct nk_panel pan;
5463  struct nk_window win;
5464 };
5465 
5470 };
5471 
5472 struct nk_page {
5473  unsigned int size;
5474  struct nk_page *next;
5476 };
5477 
5478 struct nk_pool {
5481  unsigned int page_count;
5482  struct nk_page *pages;
5484  unsigned capacity;
5487 };
5488 
5489 struct nk_context {
5490 /* public: can be accessed freely */
5491  struct nk_input input;
5492  struct nk_style style;
5499 
5500 /* private:
5501  should only be accessed if you
5502  know what you are doing */
5503 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
5504  struct nk_draw_list draw_list;
5505 #endif
5506 #ifdef NK_INCLUDE_COMMAND_USERDATA
5507  nk_handle userdata;
5508 #endif
5509  /* text editor objects are quite big because of an internal
5510  * undo/redo stack. Therefore it does not make sense to have one for
5511  * each window for temporary use cases, so I only provide *one* instance
5512  * for all windows. This works because the content is cleared anyway */
5514  /* draw buffer used for overlay drawing operation like cursor */
5516 
5517  /* windows */
5518  int build;
5520  struct nk_pool pool;
5521  struct nk_window *begin;
5522  struct nk_window *end;
5526  unsigned int count;
5527  unsigned int seq;
5528 };
5529 
5530 /* ==============================================================
5531  * MATH
5532  * =============================================================== */
5533 #define NK_PI 3.141592654f
5534 #define NK_UTF_INVALID 0xFFFD
5535 #define NK_MAX_FLOAT_PRECISION 2
5536 
5537 #define NK_UNUSED(x) ((void)(x))
5538 #define NK_SATURATE(x) (NK_MAX(0, NK_MIN(1.0f, x)))
5539 #define NK_LEN(a) (sizeof(a)/sizeof(a)[0])
5540 #define NK_ABS(a) (((a) < 0) ? -(a) : (a))
5541 #define NK_BETWEEN(x, a, b) ((a) <= (x) && (x) < (b))
5542 #define NK_INBOX(px, py, x, y, w, h)\
5543  (NK_BETWEEN(px,x,x+w) && NK_BETWEEN(py,y,y+h))
5544 #define NK_INTERSECT(x0, y0, w0, h0, x1, y1, w1, h1) \
5545  (!(((x1 > (x0 + w0)) || ((x1 + w1) < x0) || (y1 > (y0 + h0)) || (y1 + h1) < y0)))
5546 #define NK_CONTAINS(x, y, w, h, bx, by, bw, bh)\
5547  (NK_INBOX(x,y, bx, by, bw, bh) && NK_INBOX(x+w,y+h, bx, by, bw, bh))
5548 
5549 #define nk_vec2_sub(a, b) nk_vec2((a).x - (b).x, (a).y - (b).y)
5550 #define nk_vec2_add(a, b) nk_vec2((a).x + (b).x, (a).y + (b).y)
5551 #define nk_vec2_len_sqr(a) ((a).x*(a).x+(a).y*(a).y)
5552 #define nk_vec2_muls(a, t) nk_vec2((a).x * (t), (a).y * (t))
5553 
5554 #define nk_ptr_add(t, p, i) ((t*)((void*)((nk_byte*)(p) + (i))))
5555 #define nk_ptr_add_const(t, p, i) ((const t*)((const void*)((const nk_byte*)(p) + (i))))
5556 #define nk_zero_struct(s) nk_zero(&s, sizeof(s))
5557 
5558 /* ==============================================================
5559  * ALIGNMENT
5560  * =============================================================== */
5561 /* Pointer to Integer type conversion for pointer alignment */
5562 #if defined(__PTRDIFF_TYPE__) /* This case should work for GCC*/
5563 # define NK_UINT_TO_PTR(x) ((void*)(__PTRDIFF_TYPE__)(x))
5564 # define NK_PTR_TO_UINT(x) ((nk_size)(__PTRDIFF_TYPE__)(x))
5565 #elif !defined(__GNUC__) /* works for compilers other than LLVM */
5566 # define NK_UINT_TO_PTR(x) ((void*)&((char*)0)[x])
5567 # define NK_PTR_TO_UINT(x) ((nk_size)(((char*)x)-(char*)0))
5568 #elif defined(NK_USE_FIXED_TYPES) /* used if we have <stdint.h> */
5569 # define NK_UINT_TO_PTR(x) ((void*)(uintptr_t)(x))
5570 # define NK_PTR_TO_UINT(x) ((uintptr_t)(x))
5571 #else /* generates warning but works */
5572 # define NK_UINT_TO_PTR(x) ((void*)(x))
5573 # define NK_PTR_TO_UINT(x) ((nk_size)(x))
5574 #endif
5575 
5576 #define NK_ALIGN_PTR(x, mask)\
5577  (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x) + (mask-1)) & ~(mask-1))))
5578 #define NK_ALIGN_PTR_BACK(x, mask)\
5579  (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x)) & ~(mask-1))))
5580 
5581 #define NK_OFFSETOF(st,m) ((nk_ptr)&(((st*)0)->m))
5582 #define NK_CONTAINER_OF(ptr,type,member)\
5583  (type*)((void*)((char*)(1 ? (ptr): &((type*)0)->member) - NK_OFFSETOF(type, member)))
5584 
5585 #ifdef __cplusplus
5586 }
5587 #endif
5588 
5589 #ifdef __cplusplus
5590 template<typename T> struct nk_alignof;
5591 template<typename T, int size_diff> struct nk_helper{enum {value = size_diff};};
5592 template<typename T> struct nk_helper<T,0>{enum {value = nk_alignof<T>::value};};
5593 template<typename T> struct nk_alignof{struct Big {T x; char c;}; enum {
5594  diff = sizeof(Big) - sizeof(T), value = nk_helper<Big, diff>::value};};
5595 #define NK_ALIGNOF(t) (nk_alignof<t>::value)
5596 #elif defined(_MSC_VER)
5597 #define NK_ALIGNOF(t) (__alignof(t))
5598 #else
5599 #define NK_ALIGNOF(t) ((char*)(&((struct {char c; t _h;}*)0)->_h) - (char*)0)
5600 #endif
5601 
5602 #endif /* NK_NUKLEAR_H_ */
5603 
5604 
5605 #ifdef NK_IMPLEMENTATION
5606 
5607 #ifndef NK_INTERNAL_H
5608 #define NK_INTERNAL_H
5609 
5610 #ifndef NK_POOL_DEFAULT_CAPACITY
5611 #define NK_POOL_DEFAULT_CAPACITY 16
5612 #endif
5613 
5614 #ifndef NK_DEFAULT_COMMAND_BUFFER_SIZE
5615 #define NK_DEFAULT_COMMAND_BUFFER_SIZE (4*1024)
5616 #endif
5617 
5618 #ifndef NK_BUFFER_DEFAULT_INITIAL_SIZE
5619 #define NK_BUFFER_DEFAULT_INITIAL_SIZE (4*1024)
5620 #endif
5621 
5622 /* standard library headers */
5623 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
5624 #include <stdlib.h> /* malloc, free */
5625 #endif
5626 #ifdef NK_INCLUDE_STANDARD_IO
5627 #include <stdio.h> /* fopen, fclose,... */
5628 #endif
5629 #ifdef NK_INCLUDE_STANDARD_VARARGS
5630 #include <stdarg.h> /* valist, va_start, va_end, ... */
5631 #endif
5632 #ifndef NK_ASSERT
5633 #include <assert.h>
5634 #define NK_ASSERT(expr) assert(expr)
5635 #endif
5636 
5637 #ifndef NK_MEMSET
5638 #define NK_MEMSET nk_memset
5639 #endif
5640 #ifndef NK_MEMCPY
5641 #define NK_MEMCPY nk_memcopy
5642 #endif
5643 #ifndef NK_SQRT
5644 #define NK_SQRT nk_sqrt
5645 #endif
5646 #ifndef NK_SIN
5647 #define NK_SIN nk_sin
5648 #endif
5649 #ifndef NK_COS
5650 #define NK_COS nk_cos
5651 #endif
5652 #ifndef NK_STRTOD
5653 #define NK_STRTOD nk_strtod
5654 #endif
5655 #ifndef NK_DTOA
5656 #define NK_DTOA nk_dtoa
5657 #endif
5658 
5659 #define NK_DEFAULT (-1)
5660 
5661 #ifndef NK_VSNPRINTF
5662 /* If your compiler does support `vsnprintf` I would highly recommend
5663  * defining this to vsnprintf instead since `vsprintf` is basically
5664  * unbelievable unsafe and should *NEVER* be used. But I have to support
5665  * it since C89 only provides this unsafe version. */
5666  #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) ||\
5667  (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
5668  (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) ||\
5669  (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) ||\
5670  defined(_ISOC99_SOURCE) || defined(_BSD_SOURCE)
5671  #define NK_VSNPRINTF(s,n,f,a) vsnprintf(s,n,f,a)
5672  #else
5673  #define NK_VSNPRINTF(s,n,f,a) vsprintf(s,f,a)
5674  #endif
5675 #endif
5676 
5677 #define NK_SCHAR_MIN (-127)
5678 #define NK_SCHAR_MAX 127
5679 #define NK_UCHAR_MIN 0
5680 #define NK_UCHAR_MAX 256
5681 #define NK_SSHORT_MIN (-32767)
5682 #define NK_SSHORT_MAX 32767
5683 #define NK_USHORT_MIN 0
5684 #define NK_USHORT_MAX 65535
5685 #define NK_SINT_MIN (-2147483647)
5686 #define NK_SINT_MAX 2147483647
5687 #define NK_UINT_MIN 0
5688 #define NK_UINT_MAX 4294967295u
5689 
5690 /* Make sure correct type size:
5691  * This will fire with a negative subscript error if the type sizes
5692  * are set incorrectly by the compiler, and compile out if not */
5693 NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*));
5694 NK_STATIC_ASSERT(sizeof(nk_ptr) == sizeof(void*));
5695 NK_STATIC_ASSERT(sizeof(nk_flags) >= 4);
5696 NK_STATIC_ASSERT(sizeof(nk_rune) >= 4);
5697 NK_STATIC_ASSERT(sizeof(nk_ushort) == 2);
5698 NK_STATIC_ASSERT(sizeof(nk_short) == 2);
5699 NK_STATIC_ASSERT(sizeof(nk_uint) == 4);
5700 NK_STATIC_ASSERT(sizeof(nk_int) == 4);
5701 NK_STATIC_ASSERT(sizeof(nk_byte) == 1);
5702 
5703 NK_GLOBAL const struct nk_rect nk_null_rect = {-8192.0f, -8192.0f, 16384, 16384};
5704 #define NK_FLOAT_PRECISION 0.00000000000001
5705 
5706 NK_GLOBAL const struct nk_color nk_red = {255,0,0,255};
5707 NK_GLOBAL const struct nk_color nk_green = {0,255,0,255};
5708 NK_GLOBAL const struct nk_color nk_blue = {0,0,255,255};
5709 NK_GLOBAL const struct nk_color nk_white = {255,255,255,255};
5710 NK_GLOBAL const struct nk_color nk_black = {0,0,0,255};
5711 NK_GLOBAL const struct nk_color nk_yellow = {255,255,0,255};
5712 
5713 /* widget */
5714 #define nk_widget_state_reset(s)\
5715  if ((*(s)) & NK_WIDGET_STATE_MODIFIED)\
5716  (*(s)) = NK_WIDGET_STATE_INACTIVE|NK_WIDGET_STATE_MODIFIED;\
5717  else (*(s)) = NK_WIDGET_STATE_INACTIVE;
5718 
5719 /* math */
5720 NK_LIB float nk_inv_sqrt(float n);
5721 NK_LIB float nk_sqrt(float x);
5722 NK_LIB float nk_sin(float x);
5723 NK_LIB float nk_cos(float x);
5724 NK_LIB nk_uint nk_round_up_pow2(nk_uint v);
5725 NK_LIB struct nk_rect nk_shrink_rect(struct nk_rect r, float amount);
5726 NK_LIB struct nk_rect nk_pad_rect(struct nk_rect r, struct nk_vec2 pad);
5727 NK_LIB void nk_unify(struct nk_rect *clip, const struct nk_rect *a, float x0, float y0, float x1, float y1);
5728 NK_LIB double nk_pow(double x, int n);
5729 NK_LIB int nk_ifloord(double x);
5730 NK_LIB int nk_ifloorf(float x);
5731 NK_LIB int nk_iceilf(float x);
5732 NK_LIB int nk_log10(double n);
5733 
5734 /* util */
5735 enum {NK_DO_NOT_STOP_ON_NEW_LINE, NK_STOP_ON_NEW_LINE};
5736 NK_LIB int nk_is_lower(int c);
5737 NK_LIB int nk_is_upper(int c);
5738 NK_LIB int nk_to_upper(int c);
5739 NK_LIB int nk_to_lower(int c);
5740 NK_LIB void* nk_memcopy(void *dst, const void *src, nk_size n);
5741 NK_LIB void nk_memset(void *ptr, int c0, nk_size size);
5742 NK_LIB void nk_zero(void *ptr, nk_size size);
5743 NK_LIB char *nk_itoa(char *s, long n);
5744 NK_LIB int nk_string_float_limit(char *string, int prec);
5745 NK_LIB char *nk_dtoa(char *s, double n);
5746 NK_LIB int nk_text_clamp(const struct nk_user_font *font, const char *text, int text_len, float space, int *glyphs, float *text_width, nk_rune *sep_list, int sep_count);
5747 NK_LIB struct nk_vec2 nk_text_calculate_text_bounds(const struct nk_user_font *font, const char *begin, int byte_len, float row_height, const char **remaining, struct nk_vec2 *out_offset, int *glyphs, int op);
5748 #ifdef NK_INCLUDE_STANDARD_VARARGS
5749 NK_LIB int nk_strfmt(char *buf, int buf_size, const char *fmt, va_list args);
5750 #endif
5751 #ifdef NK_INCLUDE_STANDARD_IO
5752 NK_LIB char *nk_file_load(const char* path, nk_size* siz, struct nk_allocator *alloc);
5753 #endif
5754 
5755 /* buffer */
5756 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
5757 NK_LIB void* nk_malloc(nk_handle unused, void *old,nk_size size);
5758 NK_LIB void nk_mfree(nk_handle unused, void *ptr);
5759 #endif
5760 NK_LIB void* nk_buffer_align(void *unaligned, nk_size align, nk_size *alignment, enum nk_buffer_allocation_type type);
5761 NK_LIB void* nk_buffer_alloc(struct nk_buffer *b, enum nk_buffer_allocation_type type, nk_size size, nk_size align);
5762 NK_LIB void* nk_buffer_realloc(struct nk_buffer *b, nk_size capacity, nk_size *size);
5763 
5764 /* draw */
5765 NK_LIB void nk_command_buffer_init(struct nk_command_buffer *cb, struct nk_buffer *b, enum nk_command_clipping clip);
5766 NK_LIB void nk_command_buffer_reset(struct nk_command_buffer *b);
5767 NK_LIB void* nk_command_buffer_push(struct nk_command_buffer* b, enum nk_command_type t, nk_size size);
5768 NK_LIB void nk_draw_symbol(struct nk_command_buffer *out, enum nk_symbol_type type, struct nk_rect content, struct nk_color background, struct nk_color foreground, float border_width, const struct nk_user_font *font);
5769 
5770 /* buffering */
5771 NK_LIB void nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *b);
5772 NK_LIB void nk_start(struct nk_context *ctx, struct nk_window *win);
5773 NK_LIB void nk_start_popup(struct nk_context *ctx, struct nk_window *win);
5774 NK_LIB void nk_finish_popup(struct nk_context *ctx, struct nk_window*);
5775 NK_LIB void nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *b);
5776 NK_LIB void nk_finish(struct nk_context *ctx, struct nk_window *w);
5777 NK_LIB void nk_build(struct nk_context *ctx);
5778 
5779 /* text editor */
5780 NK_LIB void nk_textedit_clear_state(struct nk_text_edit *state, enum nk_text_edit_type type, nk_plugin_filter filter);
5781 NK_LIB void nk_textedit_click(struct nk_text_edit *state, float x, float y, const struct nk_user_font *font, float row_height);
5782 NK_LIB void nk_textedit_drag(struct nk_text_edit *state, float x, float y, const struct nk_user_font *font, float row_height);
5783 NK_LIB void nk_textedit_key(struct nk_text_edit *state, enum nk_keys key, int shift_mod, const struct nk_user_font *font, float row_height);
5784 
5785 /* window */
5786 enum nk_window_insert_location {
5787  NK_INSERT_BACK, /* inserts window into the back of list (front of screen) */
5788  NK_INSERT_FRONT /* inserts window into the front of list (back of screen) */
5789 };
5790 NK_LIB void *nk_create_window(struct nk_context *ctx);
5791 NK_LIB void nk_remove_window(struct nk_context*, struct nk_window*);
5792 NK_LIB void nk_free_window(struct nk_context *ctx, struct nk_window *win);
5793 NK_LIB struct nk_window *nk_find_window(struct nk_context *ctx, nk_hash hash, const char *name);
5794 NK_LIB void nk_insert_window(struct nk_context *ctx, struct nk_window *win, enum nk_window_insert_location loc);
5795 
5796 /* pool */
5797 NK_LIB void nk_pool_init(struct nk_pool *pool, struct nk_allocator *alloc, unsigned int capacity);
5798 NK_LIB void nk_pool_free(struct nk_pool *pool);
5799 NK_LIB void nk_pool_init_fixed(struct nk_pool *pool, void *memory, nk_size size);
5800 NK_LIB struct nk_page_element *nk_pool_alloc(struct nk_pool *pool);
5801 
5802 /* page-element */
5803 NK_LIB struct nk_page_element* nk_create_page_element(struct nk_context *ctx);
5804 NK_LIB void nk_link_page_element_into_freelist(struct nk_context *ctx, struct nk_page_element *elem);
5805 NK_LIB void nk_free_page_element(struct nk_context *ctx, struct nk_page_element *elem);
5806 
5807 /* table */
5808 NK_LIB struct nk_table* nk_create_table(struct nk_context *ctx);
5809 NK_LIB void nk_remove_table(struct nk_window *win, struct nk_table *tbl);
5810 NK_LIB void nk_free_table(struct nk_context *ctx, struct nk_table *tbl);
5811 NK_LIB void nk_push_table(struct nk_window *win, struct nk_table *tbl);
5812 NK_LIB nk_uint *nk_add_value(struct nk_context *ctx, struct nk_window *win, nk_hash name, nk_uint value);
5813 NK_LIB nk_uint *nk_find_value(struct nk_window *win, nk_hash name);
5814 
5815 /* panel */
5816 NK_LIB void *nk_create_panel(struct nk_context *ctx);
5817 NK_LIB void nk_free_panel(struct nk_context*, struct nk_panel *pan);
5818 NK_LIB int nk_panel_has_header(nk_flags flags, const char *title);
5819 NK_LIB struct nk_vec2 nk_panel_get_padding(const struct nk_style *style, enum nk_panel_type type);
5820 NK_LIB float nk_panel_get_border(const struct nk_style *style, nk_flags flags, enum nk_panel_type type);
5821 NK_LIB struct nk_color nk_panel_get_border_color(const struct nk_style *style, enum nk_panel_type type);
5822 NK_LIB int nk_panel_is_sub(enum nk_panel_type type);
5823 NK_LIB int nk_panel_is_nonblock(enum nk_panel_type type);
5824 NK_LIB int nk_panel_begin(struct nk_context *ctx, const char *title, enum nk_panel_type panel_type);
5825 NK_LIB void nk_panel_end(struct nk_context *ctx);
5826 
5827 /* layout */
5828 NK_LIB float nk_layout_row_calculate_usable_space(const struct nk_style *style, enum nk_panel_type type, float total_space, int columns);
5829 NK_LIB void nk_panel_layout(const struct nk_context *ctx, struct nk_window *win, float height, int cols);
5830 NK_LIB void nk_row_layout(struct nk_context *ctx, enum nk_layout_format fmt, float height, int cols, int width);
5831 NK_LIB void nk_panel_alloc_row(const struct nk_context *ctx, struct nk_window *win);
5832 NK_LIB void nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx, struct nk_window *win, int modify);
5833 NK_LIB void nk_panel_alloc_space(struct nk_rect *bounds, const struct nk_context *ctx);
5834 NK_LIB void nk_layout_peek(struct nk_rect *bounds, struct nk_context *ctx);
5835 
5836 /* popup */
5837 NK_LIB int nk_nonblock_begin(struct nk_context *ctx, nk_flags flags, struct nk_rect body, struct nk_rect header, enum nk_panel_type panel_type);
5838 
5839 /* text */
5840 struct nk_text {
5841  struct nk_vec2 padding;
5842  struct nk_color background;
5843  struct nk_color text;
5844 };
5845 NK_LIB void nk_widget_text(struct nk_command_buffer *o, struct nk_rect b, const char *string, int len, const struct nk_text *t, nk_flags a, const struct nk_user_font *f);
5846 NK_LIB void nk_widget_text_wrap(struct nk_command_buffer *o, struct nk_rect b, const char *string, int len, const struct nk_text *t, const struct nk_user_font *f);
5847 
5848 /* button */
5849 NK_LIB int nk_button_behavior(nk_flags *state, struct nk_rect r, const struct nk_input *i, enum nk_button_behavior behavior);
5850 NK_LIB const struct nk_style_item* nk_draw_button(struct nk_command_buffer *out, const struct nk_rect *bounds, nk_flags state, const struct nk_style_button *style);
5851 NK_LIB int nk_do_button(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r, const struct nk_style_button *style, const struct nk_input *in, enum nk_button_behavior behavior, struct nk_rect *content);
5852 NK_LIB void nk_draw_button_text(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state, const struct nk_style_button *style, const char *txt, int len, nk_flags text_alignment, const struct nk_user_font *font);
5853 NK_LIB int nk_do_button_text(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, const char *string, int len, nk_flags align, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_input *in, const struct nk_user_font *font);
5854 NK_LIB void nk_draw_button_symbol(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state, const struct nk_style_button *style, enum nk_symbol_type type, const struct nk_user_font *font);
5855 NK_LIB int nk_do_button_symbol(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, enum nk_symbol_type symbol, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_input *in, const struct nk_user_font *font);
5856 NK_LIB void nk_draw_button_image(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state, const struct nk_style_button *style, const struct nk_image *img);
5857 NK_LIB int nk_do_button_image(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, struct nk_image img, enum nk_button_behavior b, const struct nk_style_button *style, const struct nk_input *in);
5858 NK_LIB void nk_draw_button_text_symbol(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *label, const struct nk_rect *symbol, nk_flags state, const struct nk_style_button *style, const char *str, int len, enum nk_symbol_type type, const struct nk_user_font *font);
5859 NK_LIB int nk_do_button_text_symbol(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, enum nk_symbol_type symbol, const char *str, int len, nk_flags align, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_user_font *font, const struct nk_input *in);
5860 NK_LIB void nk_draw_button_text_image(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *label, const struct nk_rect *image, nk_flags state, const struct nk_style_button *style, const char *str, int len, const struct nk_user_font *font, const struct nk_image *img);
5861 NK_LIB int nk_do_button_text_image(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, struct nk_image img, const char* str, int len, nk_flags align, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_user_font *font, const struct nk_input *in);
5862 
5863 /* toggle */
5864 enum nk_toggle_type {
5865  NK_TOGGLE_CHECK,
5866  NK_TOGGLE_OPTION
5867 };
5868 NK_LIB int nk_toggle_behavior(const struct nk_input *in, struct nk_rect select, nk_flags *state, int active);
5869 NK_LIB void nk_draw_checkbox(struct nk_command_buffer *out, nk_flags state, const struct nk_style_toggle *style, int active, const struct nk_rect *label, const struct nk_rect *selector, const struct nk_rect *cursors, const char *string, int len, const struct nk_user_font *font);
5870 NK_LIB void nk_draw_option(struct nk_command_buffer *out, nk_flags state, const struct nk_style_toggle *style, int active, const struct nk_rect *label, const struct nk_rect *selector, const struct nk_rect *cursors, const char *string, int len, const struct nk_user_font *font);
5871 NK_LIB int nk_do_toggle(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r, int *active, const char *str, int len, enum nk_toggle_type type, const struct nk_style_toggle *style, const struct nk_input *in, const struct nk_user_font *font);
5872 
5873 /* progress */
5874 NK_LIB nk_size nk_progress_behavior(nk_flags *state, struct nk_input *in, struct nk_rect r, struct nk_rect cursor, nk_size max, nk_size value, int modifiable);
5875 NK_LIB void nk_draw_progress(struct nk_command_buffer *out, nk_flags state, const struct nk_style_progress *style, const struct nk_rect *bounds, const struct nk_rect *scursor, nk_size value, nk_size max);
5876 NK_LIB nk_size nk_do_progress(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, nk_size value, nk_size max, int modifiable, const struct nk_style_progress *style, struct nk_input *in);
5877 
5878 /* slider */
5879 NK_LIB float nk_slider_behavior(nk_flags *state, struct nk_rect *logical_cursor, struct nk_rect *visual_cursor, struct nk_input *in, struct nk_rect bounds, float slider_min, float slider_max, float slider_value, float slider_step, float slider_steps);
5880 NK_LIB void nk_draw_slider(struct nk_command_buffer *out, nk_flags state, const struct nk_style_slider *style, const struct nk_rect *bounds, const struct nk_rect *visual_cursor, float min, float value, float max);
5881 NK_LIB float nk_do_slider(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, float min, float val, float max, float step, const struct nk_style_slider *style, struct nk_input *in, const struct nk_user_font *font);
5882 
5883 /* scrollbar */
5884 NK_LIB float nk_scrollbar_behavior(nk_flags *state, struct nk_input *in, int has_scrolling, const struct nk_rect *scroll, const struct nk_rect *cursor, const struct nk_rect *empty0, const struct nk_rect *empty1, float scroll_offset, float target, float scroll_step, enum nk_orientation o);
5885 NK_LIB void nk_draw_scrollbar(struct nk_command_buffer *out, nk_flags state, const struct nk_style_scrollbar *style, const struct nk_rect *bounds, const struct nk_rect *scroll);
5886 NK_LIB float nk_do_scrollbarv(nk_flags *state, struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling, float offset, float target, float step, float button_pixel_inc, const struct nk_style_scrollbar *style, struct nk_input *in, const struct nk_user_font *font);
5887 NK_LIB float nk_do_scrollbarh(nk_flags *state, struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling, float offset, float target, float step, float button_pixel_inc, const struct nk_style_scrollbar *style, struct nk_input *in, const struct nk_user_font *font);
5888 
5889 /* selectable */
5890 NK_LIB void nk_draw_selectable(struct nk_command_buffer *out, nk_flags state, const struct nk_style_selectable *style, int active, const struct nk_rect *bounds, const struct nk_rect *icon, const struct nk_image *img, enum nk_symbol_type sym, const char *string, int len, nk_flags align, const struct nk_user_font *font);
5891 NK_LIB int nk_do_selectable(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, const char *str, int len, nk_flags align, int *value, const struct nk_style_selectable *style, const struct nk_input *in, const struct nk_user_font *font);
5892 NK_LIB int nk_do_selectable_image(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, const char *str, int len, nk_flags align, int *value, const struct nk_image *img, const struct nk_style_selectable *style, const struct nk_input *in, const struct nk_user_font *font);
5893 
5894 /* edit */
5895 NK_LIB void nk_edit_draw_text(struct nk_command_buffer *out, const struct nk_style_edit *style, float pos_x, float pos_y, float x_offset, const char *text, int byte_len, float row_height, const struct nk_user_font *font, struct nk_color background, struct nk_color foreground, int is_selected);
5896 NK_LIB nk_flags nk_do_edit(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, nk_flags flags, nk_plugin_filter filter, struct nk_text_edit *edit, const struct nk_style_edit *style, struct nk_input *in, const struct nk_user_font *font);
5897 
5898 /* color-picker */
5899 NK_LIB int nk_color_picker_behavior(nk_flags *state, const struct nk_rect *bounds, const struct nk_rect *matrix, const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar, struct nk_colorf *color, const struct nk_input *in);
5900 NK_LIB void nk_draw_color_picker(struct nk_command_buffer *o, const struct nk_rect *matrix, const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar, struct nk_colorf col);
5901 NK_LIB int nk_do_color_picker(nk_flags *state, struct nk_command_buffer *out, struct nk_colorf *col, enum nk_color_format fmt, struct nk_rect bounds, struct nk_vec2 padding, const struct nk_input *in, const struct nk_user_font *font);
5902 
5903 /* property */
5904 enum nk_property_status {
5905  NK_PROPERTY_DEFAULT,
5906  NK_PROPERTY_EDIT,
5907  NK_PROPERTY_DRAG
5908 };
5909 enum nk_property_filter {
5910  NK_FILTER_INT,
5911  NK_FILTER_FLOAT
5912 };
5913 enum nk_property_kind {
5914  NK_PROPERTY_INT,
5915  NK_PROPERTY_FLOAT,
5916  NK_PROPERTY_DOUBLE
5917 };
5918 union nk_property {
5919  int i;
5920  float f;
5921  double d;
5922 };
5923 struct nk_property_variant {
5924  enum nk_property_kind kind;
5925  union nk_property value;
5926  union nk_property min_value;
5927  union nk_property max_value;
5928  union nk_property step;
5929 };
5930 NK_LIB struct nk_property_variant nk_property_variant_int(int value, int min_value, int max_value, int step);
5931 NK_LIB struct nk_property_variant nk_property_variant_float(float value, float min_value, float max_value, float step);
5932 NK_LIB struct nk_property_variant nk_property_variant_double(double value, double min_value, double max_value, double step);
5933 
5934 NK_LIB void nk_drag_behavior(nk_flags *state, const struct nk_input *in, struct nk_rect drag, struct nk_property_variant *variant, float inc_per_pixel);
5935 NK_LIB void nk_property_behavior(nk_flags *ws, const struct nk_input *in, struct nk_rect property, struct nk_rect label, struct nk_rect edit, struct nk_rect empty, int *state, struct nk_property_variant *variant, float inc_per_pixel);
5936 NK_LIB void nk_draw_property(struct nk_command_buffer *out, const struct nk_style_property *style, const struct nk_rect *bounds, const struct nk_rect *label, nk_flags state, const char *name, int len, const struct nk_user_font *font);
5937 NK_LIB void nk_do_property(nk_flags *ws, struct nk_command_buffer *out, struct nk_rect property, const char *name, struct nk_property_variant *variant, float inc_per_pixel, char *buffer, int *len, int *state, int *cursor, int *select_begin, int *select_end, const struct nk_style_property *style, enum nk_property_filter filter, struct nk_input *in, const struct nk_user_font *font, struct nk_text_edit *text_edit, enum nk_button_behavior behavior);
5938 NK_LIB void nk_property(struct nk_context *ctx, const char *name, struct nk_property_variant *variant, float inc_per_pixel, const enum nk_property_filter filter);
5939 
5940 #endif
5941 
5942 
5943 
5944 
5945 
5946 /* ===============================================================
5947  *
5948  * MATH
5949  *
5950  * ===============================================================*/
5951 /* Since nuklear is supposed to work on all systems providing floating point
5952  math without any dependencies I also had to implement my own math functions
5953  for sqrt, sin and cos. Since the actual highly accurate implementations for
5954  the standard library functions are quite complex and I do not need high
5955  precision for my use cases I use approximations.
5956 
5957  Sqrt
5958  ----
5959  For square root nuklear uses the famous fast inverse square root:
5960  https://en.wikipedia.org/wiki/Fast_inverse_square_root with
5961  slightly tweaked magic constant. While on today's hardware it is
5962  probably not faster it is still fast and accurate enough for
5963  nuklear's use cases. IMPORTANT: this requires float format IEEE 754
5964 
5965  Sine/Cosine
5966  -----------
5967  All constants inside both function are generated Remez's minimax
5968  approximations for value range 0...2*PI. The reason why I decided to
5969  approximate exactly that range is that nuklear only needs sine and
5970  cosine to generate circles which only requires that exact range.
5971  In addition I used Remez instead of Taylor for additional precision:
5972  www.lolengine.net/blog/2011/12/21/better-function-approximations.
5973 
5974  The tool I used to generate constants for both sine and cosine
5975  (it can actually approximate a lot more functions) can be
5976  found here: www.lolengine.net/wiki/oss/lolremez
5977 */
5978 NK_LIB float
5979 nk_inv_sqrt(float n)
5980 {
5981  float x2;
5982  const float threehalfs = 1.5f;
5983  union {nk_uint i; float f;} conv = {0};
5984  conv.f = n;
5985  x2 = n * 0.5f;
5986  conv.i = 0x5f375A84 - (conv.i >> 1);
5987  conv.f = conv.f * (threehalfs - (x2 * conv.f * conv.f));
5988  return conv.f;
5989 }
5990 NK_LIB float
5991 nk_sqrt(float x)
5992 {
5993  return x * nk_inv_sqrt(x);
5994 }
5995 NK_LIB float
5996 nk_sin(float x)
5997 {
5998  NK_STORAGE const float a0 = +1.91059300966915117e-31f;
5999  NK_STORAGE const float a1 = +1.00086760103908896f;
6000  NK_STORAGE const float a2 = -1.21276126894734565e-2f;
6001  NK_STORAGE const float a3 = -1.38078780785773762e-1f;
6002  NK_STORAGE const float a4 = -2.67353392911981221e-2f;
6003  NK_STORAGE const float a5 = +2.08026600266304389e-2f;
6004  NK_STORAGE const float a6 = -3.03996055049204407e-3f;
6005  NK_STORAGE const float a7 = +1.38235642404333740e-4f;
6006  return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7))))));
6007 }
6008 NK_LIB float
6009 nk_cos(float x)
6010 {
6011  NK_STORAGE const float a0 = +1.00238601909309722f;
6012  NK_STORAGE const float a1 = -3.81919947353040024e-2f;
6013  NK_STORAGE const float a2 = -3.94382342128062756e-1f;
6014  NK_STORAGE const float a3 = -1.18134036025221444e-1f;
6015  NK_STORAGE const float a4 = +1.07123798512170878e-1f;
6016  NK_STORAGE const float a5 = -1.86637164165180873e-2f;
6017  NK_STORAGE const float a6 = +9.90140908664079833e-4f;
6018  NK_STORAGE const float a7 = -5.23022132118824778e-14f;
6019  return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7))))));
6020 }
6022 nk_round_up_pow2(nk_uint v)
6023 {
6024  v--;
6025  v |= v >> 1;
6026  v |= v >> 2;
6027  v |= v >> 4;
6028  v |= v >> 8;
6029  v |= v >> 16;
6030  v++;
6031  return v;
6032 }
6033 NK_LIB double
6034 nk_pow(double x, int n)
6035 {
6036  /* check the sign of n */
6037  double r = 1;
6038  int plus = n >= 0;
6039  n = (plus) ? n : -n;
6040  while (n > 0) {
6041  if ((n & 1) == 1)
6042  r *= x;
6043  n /= 2;
6044  x *= x;
6045  }
6046  return plus ? r : 1.0 / r;
6047 }
6048 NK_LIB int
6049 nk_ifloord(double x)
6050 {
6051  x = (double)((int)x - ((x < 0.0) ? 1 : 0));
6052  return (int)x;
6053 }
6054 NK_LIB int
6055 nk_ifloorf(float x)
6056 {
6057  x = (float)((int)x - ((x < 0.0f) ? 1 : 0));
6058  return (int)x;
6059 }
6060 NK_LIB int
6061 nk_iceilf(float x)
6062 {
6063  if (x >= 0) {
6064  int i = (int)x;
6065  return (x > i) ? i+1: i;
6066  } else {
6067  int t = (int)x;
6068  float r = x - (float)t;
6069  return (r > 0.0f) ? t+1: t;
6070  }
6071 }
6072 NK_LIB int
6073 nk_log10(double n)
6074 {
6075  int neg;
6076  int ret;
6077  int exp = 0;
6078 
6079  neg = (n < 0) ? 1 : 0;
6080  ret = (neg) ? (int)-n : (int)n;
6081  while ((ret / 10) > 0) {
6082  ret /= 10;
6083  exp++;
6084  }
6085  if (neg) exp = -exp;
6086  return exp;
6087 }
6088 NK_API struct nk_rect
6089 nk_get_null_rect(void)
6090 {
6091  return nk_null_rect;
6092 }
6093 NK_API struct nk_rect
6094 nk_rect(float x, float y, float w, float h)
6095 {
6096  struct nk_rect r;
6097  r.x = x; r.y = y;
6098  r.w = w; r.h = h;
6099  return r;
6100 }
6101 NK_API struct nk_rect
6102 nk_recti(int x, int y, int w, int h)
6103 {
6104  struct nk_rect r;
6105  r.x = (float)x;
6106  r.y = (float)y;
6107  r.w = (float)w;
6108  r.h = (float)h;
6109  return r;
6110 }
6111 NK_API struct nk_rect
6112 nk_recta(struct nk_vec2 pos, struct nk_vec2 size)
6113 {
6114  return nk_rect(pos.x, pos.y, size.x, size.y);
6115 }
6116 NK_API struct nk_rect
6117 nk_rectv(const float *r)
6118 {
6119  return nk_rect(r[0], r[1], r[2], r[3]);
6120 }
6121 NK_API struct nk_rect
6122 nk_rectiv(const int *r)
6123 {
6124  return nk_recti(r[0], r[1], r[2], r[3]);
6125 }
6126 NK_API struct nk_vec2
6127 nk_rect_pos(struct nk_rect r)
6128 {
6129  struct nk_vec2 ret;
6130  ret.x = r.x; ret.y = r.y;
6131  return ret;
6132 }
6133 NK_API struct nk_vec2
6134 nk_rect_size(struct nk_rect r)
6135 {
6136  struct nk_vec2 ret;
6137  ret.x = r.w; ret.y = r.h;
6138  return ret;
6139 }
6140 NK_LIB struct nk_rect
6141 nk_shrink_rect(struct nk_rect r, float amount)
6142 {
6143  struct nk_rect res;
6144  r.w = NK_MAX(r.w, 2 * amount);
6145  r.h = NK_MAX(r.h, 2 * amount);
6146  res.x = r.x + amount;
6147  res.y = r.y + amount;
6148  res.w = r.w - 2 * amount;
6149  res.h = r.h - 2 * amount;
6150  return res;
6151 }
6152 NK_LIB struct nk_rect
6153 nk_pad_rect(struct nk_rect r, struct nk_vec2 pad)
6154 {
6155  r.w = NK_MAX(r.w, 2 * pad.x);
6156  r.h = NK_MAX(r.h, 2 * pad.y);
6157  r.x += pad.x; r.y += pad.y;
6158  r.w -= 2 * pad.x;
6159  r.h -= 2 * pad.y;
6160  return r;
6161 }
6162 NK_API struct nk_vec2
6163 nk_vec2(float x, float y)
6164 {
6165  struct nk_vec2 ret;
6166  ret.x = x; ret.y = y;
6167  return ret;
6168 }
6169 NK_API struct nk_vec2
6170 nk_vec2i(int x, int y)
6171 {
6172  struct nk_vec2 ret;
6173  ret.x = (float)x;
6174  ret.y = (float)y;
6175  return ret;
6176 }
6177 NK_API struct nk_vec2
6178 nk_vec2v(const float *v)
6179 {
6180  return nk_vec2(v[0], v[1]);
6181 }
6182 NK_API struct nk_vec2
6183 nk_vec2iv(const int *v)
6184 {
6185  return nk_vec2i(v[0], v[1]);
6186 }
6187 NK_LIB void
6188 nk_unify(struct nk_rect *clip, const struct nk_rect *a, float x0, float y0,
6189  float x1, float y1)
6190 {
6191  NK_ASSERT(a);
6192  NK_ASSERT(clip);
6193  clip->x = NK_MAX(a->x, x0);
6194  clip->y = NK_MAX(a->y, y0);
6195  clip->w = NK_MIN(a->x + a->w, x1) - clip->x;
6196  clip->h = NK_MIN(a->y + a->h, y1) - clip->y;
6197  clip->w = NK_MAX(0, clip->w);
6198  clip->h = NK_MAX(0, clip->h);
6199 }
6200 
6201 NK_API void
6202 nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r,
6203  float pad_x, float pad_y, enum nk_heading direction)
6204 {
6205  float w_half, h_half;
6206  NK_ASSERT(result);
6207 
6208  r.w = NK_MAX(2 * pad_x, r.w);
6209  r.h = NK_MAX(2 * pad_y, r.h);
6210  r.w = r.w - 2 * pad_x;
6211  r.h = r.h - 2 * pad_y;
6212 
6213  r.x = r.x + pad_x;
6214  r.y = r.y + pad_y;
6215 
6216  w_half = r.w / 2.0f;
6217  h_half = r.h / 2.0f;
6218 
6219  if (direction == NK_UP) {
6220  result[0] = nk_vec2(r.x + w_half, r.y);
6221  result[1] = nk_vec2(r.x + r.w, r.y + r.h);
6222  result[2] = nk_vec2(r.x, r.y + r.h);
6223  } else if (direction == NK_RIGHT) {
6224  result[0] = nk_vec2(r.x, r.y);
6225  result[1] = nk_vec2(r.x + r.w, r.y + h_half);
6226  result[2] = nk_vec2(r.x, r.y + r.h);
6227  } else if (direction == NK_DOWN) {
6228  result[0] = nk_vec2(r.x, r.y);
6229  result[1] = nk_vec2(r.x + r.w, r.y);
6230  result[2] = nk_vec2(r.x + w_half, r.y + r.h);
6231  } else {
6232  result[0] = nk_vec2(r.x, r.y + h_half);
6233  result[1] = nk_vec2(r.x + r.w, r.y);
6234  result[2] = nk_vec2(r.x + r.w, r.y + r.h);
6235  }
6236 }
6237 
6238 
6239 
6240 
6241 
6242 /* ===============================================================
6243  *
6244  * UTIL
6245  *
6246  * ===============================================================*/
6247 NK_INTERN int nk_str_match_here(const char *regexp, const char *text);
6248 NK_INTERN int nk_str_match_star(int c, const char *regexp, const char *text);
6249 NK_LIB int nk_is_lower(int c) {return (c >= 'a' && c <= 'z') || (c >= 0xE0 && c <= 0xFF);}
6250 NK_LIB int nk_is_upper(int c){return (c >= 'A' && c <= 'Z') || (c >= 0xC0 && c <= 0xDF);}
6251 NK_LIB int nk_to_upper(int c) {return (c >= 'a' && c <= 'z') ? (c - ('a' - 'A')) : c;}
6252 NK_LIB int nk_to_lower(int c) {return (c >= 'A' && c <= 'Z') ? (c - ('a' + 'A')) : c;}
6253 
6254 NK_LIB void*
6255 nk_memcopy(void *dst0, const void *src0, nk_size length)
6256 {
6257  nk_ptr t;
6258  char *dst = (char*)dst0;
6259  const char *src = (const char*)src0;
6260  if (length == 0 || dst == src)
6261  goto done;
6262 
6263  #define nk_word int
6264  #define nk_wsize sizeof(nk_word)
6265  #define nk_wmask (nk_wsize-1)
6266  #define NK_TLOOP(s) if (t) NK_TLOOP1(s)
6267  #define NK_TLOOP1(s) do { s; } while (--t)
6268 
6269  if (dst < src) {
6270  t = (nk_ptr)src; /* only need low bits */
6271  if ((t | (nk_ptr)dst) & nk_wmask) {
6272  if ((t ^ (nk_ptr)dst) & nk_wmask || length < nk_wsize)
6273  t = length;
6274  else
6275  t = nk_wsize - (t & nk_wmask);
6276  length -= t;
6277  NK_TLOOP1(*dst++ = *src++);
6278  }
6279  t = length / nk_wsize;
6280  NK_TLOOP(*(nk_word*)(void*)dst = *(const nk_word*)(const void*)src;
6281  src += nk_wsize; dst += nk_wsize);
6282  t = length & nk_wmask;
6283  NK_TLOOP(*dst++ = *src++);
6284  } else {
6285  src += length;
6286  dst += length;
6287  t = (nk_ptr)src;
6288  if ((t | (nk_ptr)dst) & nk_wmask) {
6289  if ((t ^ (nk_ptr)dst) & nk_wmask || length <= nk_wsize)
6290  t = length;
6291  else
6292  t &= nk_wmask;
6293  length -= t;
6294  NK_TLOOP1(*--dst = *--src);
6295  }
6296  t = length / nk_wsize;
6297  NK_TLOOP(src -= nk_wsize; dst -= nk_wsize;
6298  *(nk_word*)(void*)dst = *(const nk_word*)(const void*)src);
6299  t = length & nk_wmask;
6300  NK_TLOOP(*--dst = *--src);
6301  }
6302  #undef nk_word
6303  #undef nk_wsize
6304  #undef nk_wmask
6305  #undef NK_TLOOP
6306  #undef NK_TLOOP1
6307 done:
6308  return (dst0);
6309 }
6310 NK_LIB void
6311 nk_memset(void *ptr, int c0, nk_size size)
6312 {
6313  #define nk_word unsigned
6314  #define nk_wsize sizeof(nk_word)
6315  #define nk_wmask (nk_wsize - 1)
6316  nk_byte *dst = (nk_byte*)ptr;
6317  unsigned c = 0;
6318  nk_size t = 0;
6319 
6320  if ((c = (nk_byte)c0) != 0) {
6321  c = (c << 8) | c; /* at least 16-bits */
6322  if (sizeof(unsigned int) > 2)
6323  c = (c << 16) | c; /* at least 32-bits*/
6324  }
6325 
6326  /* too small of a word count */
6327  dst = (nk_byte*)ptr;
6328  if (size < 3 * nk_wsize) {
6329  while (size--) *dst++ = (nk_byte)c0;
6330  return;
6331  }
6332 
6333  /* align destination */
6334  if ((t = NK_PTR_TO_UINT(dst) & nk_wmask) != 0) {
6335  t = nk_wsize -t;
6336  size -= t;
6337  do {
6338  *dst++ = (nk_byte)c0;
6339  } while (--t != 0);
6340  }
6341 
6342  /* fill word */
6343  t = size / nk_wsize;
6344  do {
6345  *(nk_word*)((void*)dst) = c;
6346  dst += nk_wsize;
6347  } while (--t != 0);
6348 
6349  /* fill trailing bytes */
6350  t = (size & nk_wmask);
6351  if (t != 0) {
6352  do {
6353  *dst++ = (nk_byte)c0;
6354  } while (--t != 0);
6355  }
6356 
6357  #undef nk_word
6358  #undef nk_wsize
6359  #undef nk_wmask
6360 }
6361 NK_LIB void
6362 nk_zero(void *ptr, nk_size size)
6363 {
6364  NK_ASSERT(ptr);
6365  NK_MEMSET(ptr, 0, size);
6366 }
6367 NK_API int
6368 nk_strlen(const char *str)
6369 {
6370  int siz = 0;
6371  NK_ASSERT(str);
6372  while (str && *str++ != '\0') siz++;
6373  return siz;
6374 }
6375 NK_API int
6376 nk_strtoi(const char *str, const char **endptr)
6377 {
6378  int neg = 1;
6379  const char *p = str;
6380  int value = 0;
6381 
6382  NK_ASSERT(str);
6383  if (!str) return 0;
6384 
6385  /* skip whitespace */
6386  while (*p == ' ') p++;
6387  if (*p == '-') {
6388  neg = -1;
6389  p++;
6390  }
6391  while (*p && *p >= '0' && *p <= '9') {
6392  value = value * 10 + (int) (*p - '0');
6393  p++;
6394  }
6395  if (endptr)
6396  *endptr = p;
6397  return neg*value;
6398 }
6399 NK_API double
6400 nk_strtod(const char *str, const char **endptr)
6401 {
6402  double m;
6403  double neg = 1.0;
6404  const char *p = str;
6405  double value = 0;
6406  double number = 0;
6407 
6408  NK_ASSERT(str);
6409  if (!str) return 0;
6410 
6411  /* skip whitespace */
6412  while (*p == ' ') p++;
6413  if (*p == '-') {
6414  neg = -1.0;
6415  p++;
6416  }
6417 
6418  while (*p && *p != '.' && *p != 'e') {
6419  value = value * 10.0 + (double) (*p - '0');
6420  p++;
6421  }
6422 
6423  if (*p == '.') {
6424  p++;
6425  for(m = 0.1; *p && *p != 'e'; p++ ) {
6426  value = value + (double) (*p - '0') * m;
6427  m *= 0.1;
6428  }
6429  }
6430  if (*p == 'e') {
6431  int i, pow, div;
6432  p++;
6433  if (*p == '-') {
6434  div = nk_true;
6435  p++;
6436  } else if (*p == '+') {
6437  div = nk_false;
6438  p++;
6439  } else div = nk_false;
6440 
6441  for (pow = 0; *p; p++)
6442  pow = pow * 10 + (int) (*p - '0');
6443 
6444  for (m = 1.0, i = 0; i < pow; i++)
6445  m *= 10.0;
6446 
6447  if (div)
6448  value /= m;
6449  else value *= m;
6450  }
6451  number = value * neg;
6452  if (endptr)
6453  *endptr = p;
6454  return number;
6455 }
6456 NK_API float
6457 nk_strtof(const char *str, const char **endptr)
6458 {
6459  float float_value;
6460  double double_value;
6461  double_value = NK_STRTOD(str, endptr);
6462  float_value = (float)double_value;
6463  return float_value;
6464 }
6465 NK_API int
6466 nk_stricmp(const char *s1, const char *s2)
6467 {
6468  nk_int c1,c2,d;
6469  do {
6470  c1 = *s1++;
6471  c2 = *s2++;
6472  d = c1 - c2;
6473  while (d) {
6474  if (c1 <= 'Z' && c1 >= 'A') {
6475  d += ('a' - 'A');
6476  if (!d) break;
6477  }
6478  if (c2 <= 'Z' && c2 >= 'A') {
6479  d -= ('a' - 'A');
6480  if (!d) break;
6481  }
6482  return ((d >= 0) << 1) - 1;
6483  }
6484  } while (c1);
6485  return 0;
6486 }
6487 NK_API int
6488 nk_stricmpn(const char *s1, const char *s2, int n)
6489 {
6490  int c1,c2,d;
6491  NK_ASSERT(n >= 0);
6492  do {
6493  c1 = *s1++;
6494  c2 = *s2++;
6495  if (!n--) return 0;
6496 
6497  d = c1 - c2;
6498  while (d) {
6499  if (c1 <= 'Z' && c1 >= 'A') {
6500  d += ('a' - 'A');
6501  if (!d) break;
6502  }
6503  if (c2 <= 'Z' && c2 >= 'A') {
6504  d -= ('a' - 'A');
6505  if (!d) break;
6506  }
6507  return ((d >= 0) << 1) - 1;
6508  }
6509  } while (c1);
6510  return 0;
6511 }
6512 NK_INTERN int
6513 nk_str_match_here(const char *regexp, const char *text)
6514 {
6515  if (regexp[0] == '\0')
6516  return 1;
6517  if (regexp[1] == '*')
6518  return nk_str_match_star(regexp[0], regexp+2, text);
6519  if (regexp[0] == '$' && regexp[1] == '\0')
6520  return *text == '\0';
6521  if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text))
6522  return nk_str_match_here(regexp+1, text+1);
6523  return 0;
6524 }
6525 NK_INTERN int
6526 nk_str_match_star(int c, const char *regexp, const char *text)
6527 {
6528  do {/* a '* matches zero or more instances */
6529  if (nk_str_match_here(regexp, text))
6530  return 1;
6531  } while (*text != '\0' && (*text++ == c || c == '.'));
6532  return 0;
6533 }
6534 NK_API int
6535 nk_strfilter(const char *text, const char *regexp)
6536 {
6537  /*
6538  c matches any literal character c
6539  . matches any single character
6540  ^ matches the beginning of the input string
6541  $ matches the end of the input string
6542  * matches zero or more occurrences of the previous character*/
6543  if (regexp[0] == '^')
6544  return nk_str_match_here(regexp+1, text);
6545  do { /* must look even if string is empty */
6546  if (nk_str_match_here(regexp, text))
6547  return 1;
6548  } while (*text++ != '\0');
6549  return 0;
6550 }
6551 NK_API int
6552 nk_strmatch_fuzzy_text(const char *str, int str_len,
6553  const char *pattern, int *out_score)
6554 {
6555  /* Returns true if each character in pattern is found sequentially within str
6556  * if found then out_score is also set. Score value has no intrinsic meaning.
6557  * Range varies with pattern. Can only compare scores with same search pattern. */
6558 
6559  /* bonus for adjacent matches */
6560  #define NK_ADJACENCY_BONUS 5
6561  /* bonus if match occurs after a separator */
6562  #define NK_SEPARATOR_BONUS 10
6563  /* bonus if match is uppercase and prev is lower */
6564  #define NK_CAMEL_BONUS 10
6565  /* penalty applied for every letter in str before the first match */
6566  #define NK_LEADING_LETTER_PENALTY (-3)
6567  /* maximum penalty for leading letters */
6568  #define NK_MAX_LEADING_LETTER_PENALTY (-9)
6569  /* penalty for every letter that doesn't matter */
6570  #define NK_UNMATCHED_LETTER_PENALTY (-1)
6571 
6572  /* loop variables */
6573  int score = 0;
6574  char const * pattern_iter = pattern;
6575  int str_iter = 0;
6576  int prev_matched = nk_false;
6577  int prev_lower = nk_false;
6578  /* true so if first letter match gets separator bonus*/
6579  int prev_separator = nk_true;
6580 
6581  /* use "best" matched letter if multiple string letters match the pattern */
6582  char const * best_letter = 0;
6583  int best_letter_score = 0;
6584 
6585  /* loop over strings */
6586  NK_ASSERT(str);
6587  NK_ASSERT(pattern);
6588  if (!str || !str_len || !pattern) return 0;
6589  while (str_iter < str_len)
6590  {
6591  const char pattern_letter = *pattern_iter;
6592  const char str_letter = str[str_iter];
6593 
6594  int next_match = *pattern_iter != '\0' &&
6595  nk_to_lower(pattern_letter) == nk_to_lower(str_letter);
6596  int rematch = best_letter && nk_to_upper(*best_letter) == nk_to_upper(str_letter);
6597 
6598  int advanced = next_match && best_letter;
6599  int pattern_repeat = best_letter && *pattern_iter != '\0';
6600  pattern_repeat = pattern_repeat &&
6601  nk_to_lower(*best_letter) == nk_to_lower(pattern_letter);
6602 
6603  if (advanced || pattern_repeat) {
6604  score += best_letter_score;
6605  best_letter = 0;
6606  best_letter_score = 0;
6607  }
6608 
6609  if (next_match || rematch)
6610  {
6611  int new_score = 0;
6612  /* Apply penalty for each letter before the first pattern match */
6613  if (pattern_iter == pattern) {
6614  int count = (int)(&str[str_iter] - str);
6615  int penalty = NK_LEADING_LETTER_PENALTY * count;
6616  if (penalty < NK_MAX_LEADING_LETTER_PENALTY)
6617  penalty = NK_MAX_LEADING_LETTER_PENALTY;
6618 
6619  score += penalty;
6620  }
6621 
6622  /* apply bonus for consecutive bonuses */
6623  if (prev_matched)
6624  new_score += NK_ADJACENCY_BONUS;
6625 
6626  /* apply bonus for matches after a separator */
6627  if (prev_separator)
6628  new_score += NK_SEPARATOR_BONUS;
6629 
6630  /* apply bonus across camel case boundaries */
6631  if (prev_lower && nk_is_upper(str_letter))
6632  new_score += NK_CAMEL_BONUS;
6633 
6634  /* update pattern iter IFF the next pattern letter was matched */
6635  if (next_match)
6636  ++pattern_iter;
6637 
6638  /* update best letter in str which may be for a "next" letter or a rematch */
6639  if (new_score >= best_letter_score) {
6640  /* apply penalty for now skipped letter */
6641  if (best_letter != 0)
6642  score += NK_UNMATCHED_LETTER_PENALTY;
6643 
6644  best_letter = &str[str_iter];
6645  best_letter_score = new_score;
6646  }
6647  prev_matched = nk_true;
6648  } else {
6649  score += NK_UNMATCHED_LETTER_PENALTY;
6650  prev_matched = nk_false;
6651  }
6652 
6653  /* separators should be more easily defined */
6654  prev_lower = nk_is_lower(str_letter) != 0;
6655  prev_separator = str_letter == '_' || str_letter == ' ';
6656 
6657  ++str_iter;
6658  }
6659 
6660  /* apply score for last match */
6661  if (best_letter)
6662  score += best_letter_score;
6663 
6664  /* did not match full pattern */
6665  if (*pattern_iter != '\0')
6666  return nk_false;
6667 
6668  if (out_score)
6669  *out_score = score;
6670  return nk_true;
6671 }
6672 NK_API int
6673 nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score)
6674 {
6675  return nk_strmatch_fuzzy_text(str, nk_strlen(str), pattern, out_score);
6676 }
6677 NK_LIB int
6678 nk_string_float_limit(char *string, int prec)
6679 {
6680  int dot = 0;
6681  char *c = string;
6682  while (*c) {
6683  if (*c == '.') {
6684  dot = 1;
6685  c++;
6686  continue;
6687  }
6688  if (dot == (prec+1)) {
6689  *c = 0;
6690  break;
6691  }
6692  if (dot > 0) dot++;
6693  c++;
6694  }
6695  return (int)(c - string);
6696 }
6697 NK_INTERN void
6698 nk_strrev_ascii(char *s)
6699 {
6700  int len = nk_strlen(s);
6701  int end = len / 2;
6702  int i = 0;
6703  char t;
6704  for (; i < end; ++i) {
6705  t = s[i];
6706  s[i] = s[len - 1 - i];
6707  s[len -1 - i] = t;
6708  }
6709 }
6710 NK_LIB char*
6711 nk_itoa(char *s, long n)
6712 {
6713  long i = 0;
6714  if (n == 0) {
6715  s[i++] = '0';
6716  s[i] = 0;
6717  return s;
6718  }
6719  if (n < 0) {
6720  s[i++] = '-';
6721  n = -n;
6722  }
6723  while (n > 0) {
6724  s[i++] = (char)('0' + (n % 10));
6725  n /= 10;
6726  }
6727  s[i] = 0;
6728  if (s[0] == '-')
6729  ++s;
6730 
6731  nk_strrev_ascii(s);
6732  return s;
6733 }
6734 NK_LIB char*
6735 nk_dtoa(char *s, double n)
6736 {
6737  int useExp = 0;
6738  int digit = 0, m = 0, m1 = 0;
6739  char *c = s;
6740  int neg = 0;
6741 
6742  NK_ASSERT(s);
6743  if (!s) return 0;
6744 
6745  if (n == 0.0) {
6746  s[0] = '0'; s[1] = '\0';
6747  return s;
6748  }
6749 
6750  neg = (n < 0);
6751  if (neg) n = -n;
6752 
6753  /* calculate magnitude */
6754  m = nk_log10(n);
6755  useExp = (m >= 14 || (neg && m >= 9) || m <= -9);
6756  if (neg) *(c++) = '-';
6757 
6758  /* set up for scientific notation */
6759  if (useExp) {
6760  if (m < 0)
6761  m -= 1;
6762  n = n / (double)nk_pow(10.0, m);
6763  m1 = m;
6764  m = 0;
6765  }
6766  if (m < 1.0) {
6767  m = 0;
6768  }
6769 
6770  /* convert the number */
6771  while (n > NK_FLOAT_PRECISION || m >= 0) {
6772  double weight = nk_pow(10.0, m);
6773  if (weight > 0) {
6774  double t = (double)n / weight;
6775  digit = nk_ifloord(t);
6776  n -= ((double)digit * weight);
6777  *(c++) = (char)('0' + (char)digit);
6778  }
6779  if (m == 0 && n > 0)
6780  *(c++) = '.';
6781  m--;
6782  }
6783 
6784  if (useExp) {
6785  /* convert the exponent */
6786  int i, j;
6787  *(c++) = 'e';
6788  if (m1 > 0) {
6789  *(c++) = '+';
6790  } else {
6791  *(c++) = '-';
6792  m1 = -m1;
6793  }
6794  m = 0;
6795  while (m1 > 0) {
6796  *(c++) = (char)('0' + (char)(m1 % 10));
6797  m1 /= 10;
6798  m++;
6799  }
6800  c -= m;
6801  for (i = 0, j = m-1; i<j; i++, j--) {
6802  /* swap without temporary */
6803  c[i] ^= c[j];
6804  c[j] ^= c[i];
6805  c[i] ^= c[j];
6806  }
6807  c += m;
6808  }
6809  *(c) = '\0';
6810  return s;
6811 }
6812 #ifdef NK_INCLUDE_STANDARD_VARARGS
6813 #ifndef NK_INCLUDE_STANDARD_IO
6814 NK_INTERN int
6815 nk_vsnprintf(char *buf, int buf_size, const char *fmt, va_list args)
6816 {
6817  enum nk_arg_type {
6818  NK_ARG_TYPE_CHAR,
6819  NK_ARG_TYPE_SHORT,
6820  NK_ARG_TYPE_DEFAULT,
6821  NK_ARG_TYPE_LONG
6822  };
6823  enum nk_arg_flags {
6824  NK_ARG_FLAG_LEFT = 0x01,
6825  NK_ARG_FLAG_PLUS = 0x02,
6826  NK_ARG_FLAG_SPACE = 0x04,
6827  NK_ARG_FLAG_NUM = 0x10,
6828  NK_ARG_FLAG_ZERO = 0x20
6829  };
6830 
6831  char number_buffer[NK_MAX_NUMBER_BUFFER];
6832  enum nk_arg_type arg_type = NK_ARG_TYPE_DEFAULT;
6833  int precision = NK_DEFAULT;
6834  int width = NK_DEFAULT;
6835  nk_flags flag = 0;
6836 
6837  int len = 0;
6838  int result = -1;
6839  const char *iter = fmt;
6840 
6841  NK_ASSERT(buf);
6842  NK_ASSERT(buf_size);
6843  if (!buf || !buf_size || !fmt) return 0;
6844  for (iter = fmt; *iter && len < buf_size; iter++) {
6845  /* copy all non-format characters */
6846  while (*iter && (*iter != '%') && (len < buf_size))
6847  buf[len++] = *iter++;
6848  if (!(*iter) || len >= buf_size) break;
6849  iter++;
6850 
6851  /* flag arguments */
6852  while (*iter) {
6853  if (*iter == '-') flag |= NK_ARG_FLAG_LEFT;
6854  else if (*iter == '+') flag |= NK_ARG_FLAG_PLUS;
6855  else if (*iter == ' ') flag |= NK_ARG_FLAG_SPACE;
6856  else if (*iter == '#') flag |= NK_ARG_FLAG_NUM;
6857  else if (*iter == '0') flag |= NK_ARG_FLAG_ZERO;
6858  else break;
6859  iter++;
6860  }
6861 
6862  /* width argument */
6863  width = NK_DEFAULT;
6864  if (*iter >= '1' && *iter <= '9') {
6865  const char *end;
6866  width = nk_strtoi(iter, &end);
6867  if (end == iter)
6868  width = -1;
6869  else iter = end;
6870  } else if (*iter == '*') {
6871  width = va_arg(args, int);
6872  iter++;
6873  }
6874 
6875  /* precision argument */
6876  precision = NK_DEFAULT;
6877  if (*iter == '.') {
6878  iter++;
6879  if (*iter == '*') {
6880  precision = va_arg(args, int);
6881  iter++;
6882  } else {
6883  const char *end;
6884  precision = nk_strtoi(iter, &end);
6885  if (end == iter)
6886  precision = -1;
6887  else iter = end;
6888  }
6889  }
6890 
6891  /* length modifier */
6892  if (*iter == 'h') {
6893  if (*(iter+1) == 'h') {
6894  arg_type = NK_ARG_TYPE_CHAR;
6895  iter++;
6896  } else arg_type = NK_ARG_TYPE_SHORT;
6897  iter++;
6898  } else if (*iter == 'l') {
6899  arg_type = NK_ARG_TYPE_LONG;
6900  iter++;
6901  } else arg_type = NK_ARG_TYPE_DEFAULT;
6902 
6903  /* specifier */
6904  if (*iter == '%') {
6905  NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
6906  NK_ASSERT(precision == NK_DEFAULT);
6907  NK_ASSERT(width == NK_DEFAULT);
6908  if (len < buf_size)
6909  buf[len++] = '%';
6910  } else if (*iter == 's') {
6911  /* string */
6912  const char *str = va_arg(args, const char*);
6913  NK_ASSERT(str != buf && "buffer and argument are not allowed to overlap!");
6914  NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
6915  NK_ASSERT(precision == NK_DEFAULT);
6916  NK_ASSERT(width == NK_DEFAULT);
6917  if (str == buf) return -1;
6918  while (str && *str && len < buf_size)
6919  buf[len++] = *str++;
6920  } else if (*iter == 'n') {
6921  /* current length callback */
6922  signed int *n = va_arg(args, int*);
6923  NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
6924  NK_ASSERT(precision == NK_DEFAULT);
6925  NK_ASSERT(width == NK_DEFAULT);
6926  if (n) *n = len;
6927  } else if (*iter == 'c' || *iter == 'i' || *iter == 'd') {
6928  /* signed integer */
6929  long value = 0;
6930  const char *num_iter;
6931  int num_len, num_print, padding;
6932  int cur_precision = NK_MAX(precision, 1);
6933  int cur_width = NK_MAX(width, 0);
6934 
6935  /* retrieve correct value type */
6936  if (arg_type == NK_ARG_TYPE_CHAR)
6937  value = (signed char)va_arg(args, int);
6938  else if (arg_type == NK_ARG_TYPE_SHORT)
6939  value = (signed short)va_arg(args, int);
6940  else if (arg_type == NK_ARG_TYPE_LONG)
6941  value = va_arg(args, signed long);
6942  else if (*iter == 'c')
6943  value = (unsigned char)va_arg(args, int);
6944  else value = va_arg(args, signed int);
6945 
6946  /* convert number to string */
6947  nk_itoa(number_buffer, value);
6948  num_len = nk_strlen(number_buffer);
6949  padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0);
6950  if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE))
6951  padding = NK_MAX(padding-1, 0);
6952 
6953  /* fill left padding up to a total of `width` characters */
6954  if (!(flag & NK_ARG_FLAG_LEFT)) {
6955  while (padding-- > 0 && (len < buf_size)) {
6956  if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT))
6957  buf[len++] = '0';
6958  else buf[len++] = ' ';
6959  }
6960  }
6961 
6962  /* copy string value representation into buffer */
6963  if ((flag & NK_ARG_FLAG_PLUS) && value >= 0 && len < buf_size)
6964  buf[len++] = '+';
6965  else if ((flag & NK_ARG_FLAG_SPACE) && value >= 0 && len < buf_size)
6966  buf[len++] = ' ';
6967 
6968  /* fill up to precision number of digits with '0' */
6969  num_print = NK_MAX(cur_precision, num_len);
6970  while (precision && (num_print > num_len) && (len < buf_size)) {
6971  buf[len++] = '0';
6972  num_print--;
6973  }
6974 
6975  /* copy string value representation into buffer */
6976  num_iter = number_buffer;
6977  while (precision && *num_iter && len < buf_size)
6978  buf[len++] = *num_iter++;
6979 
6980  /* fill right padding up to width characters */
6981  if (flag & NK_ARG_FLAG_LEFT) {
6982  while ((padding-- > 0) && (len < buf_size))
6983  buf[len++] = ' ';
6984  }
6985  } else if (*iter == 'o' || *iter == 'x' || *iter == 'X' || *iter == 'u') {
6986  /* unsigned integer */
6987  unsigned long value = 0;
6988  int num_len = 0, num_print, padding = 0;
6989  int cur_precision = NK_MAX(precision, 1);
6990  int cur_width = NK_MAX(width, 0);
6991  unsigned int base = (*iter == 'o') ? 8: (*iter == 'u')? 10: 16;
6992 
6993  /* print oct/hex/dec value */
6994  const char *upper_output_format = "0123456789ABCDEF";
6995  const char *lower_output_format = "0123456789abcdef";
6996  const char *output_format = (*iter == 'x') ?
6997  lower_output_format: upper_output_format;
6998 
6999  /* retrieve correct value type */
7000  if (arg_type == NK_ARG_TYPE_CHAR)
7001  value = (unsigned char)va_arg(args, int);
7002  else if (arg_type == NK_ARG_TYPE_SHORT)
7003  value = (unsigned short)va_arg(args, int);
7004  else if (arg_type == NK_ARG_TYPE_LONG)
7005  value = va_arg(args, unsigned long);
7006  else value = va_arg(args, unsigned int);
7007 
7008  do {
7009  /* convert decimal number into hex/oct number */
7010  int digit = output_format[value % base];
7011  if (num_len < NK_MAX_NUMBER_BUFFER)
7012  number_buffer[num_len++] = (char)digit;
7013  value /= base;
7014  } while (value > 0);
7015 
7016  num_print = NK_MAX(cur_precision, num_len);
7017  padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0);
7018  if (flag & NK_ARG_FLAG_NUM)
7019  padding = NK_MAX(padding-1, 0);
7020 
7021  /* fill left padding up to a total of `width` characters */
7022  if (!(flag & NK_ARG_FLAG_LEFT)) {
7023  while ((padding-- > 0) && (len < buf_size)) {
7024  if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT))
7025  buf[len++] = '0';
7026  else buf[len++] = ' ';
7027  }
7028  }
7029 
7030  /* fill up to precision number of digits */
7031  if (num_print && (flag & NK_ARG_FLAG_NUM)) {
7032  if ((*iter == 'o') && (len < buf_size)) {
7033  buf[len++] = '0';
7034  } else if ((*iter == 'x') && ((len+1) < buf_size)) {
7035  buf[len++] = '0';
7036  buf[len++] = 'x';
7037  } else if ((*iter == 'X') && ((len+1) < buf_size)) {
7038  buf[len++] = '0';
7039  buf[len++] = 'X';
7040  }
7041  }
7042  while (precision && (num_print > num_len) && (len < buf_size)) {
7043  buf[len++] = '0';
7044  num_print--;
7045  }
7046 
7047  /* reverse number direction */
7048  while (num_len > 0) {
7049  if (precision && (len < buf_size))
7050  buf[len++] = number_buffer[num_len-1];
7051  num_len--;
7052  }
7053 
7054  /* fill right padding up to width characters */
7055  if (flag & NK_ARG_FLAG_LEFT) {
7056  while ((padding-- > 0) && (len < buf_size))
7057  buf[len++] = ' ';
7058  }
7059  } else if (*iter == 'f') {
7060  /* floating point */
7061  const char *num_iter;
7062  int cur_precision = (precision < 0) ? 6: precision;
7063  int prefix, cur_width = NK_MAX(width, 0);
7064  double value = va_arg(args, double);
7065  int num_len = 0, frac_len = 0, dot = 0;
7066  int padding = 0;
7067 
7068  NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
7069  NK_DTOA(number_buffer, value);
7070  num_len = nk_strlen(number_buffer);
7071 
7072  /* calculate padding */
7073  num_iter = number_buffer;
7074  while (*num_iter && *num_iter != '.')
7075  num_iter++;
7076 
7077  prefix = (*num_iter == '.')?(int)(num_iter - number_buffer)+1:0;
7078  padding = NK_MAX(cur_width - (prefix + NK_MIN(cur_precision, num_len - prefix)) , 0);
7079  if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE))
7080  padding = NK_MAX(padding-1, 0);
7081 
7082  /* fill left padding up to a total of `width` characters */
7083  if (!(flag & NK_ARG_FLAG_LEFT)) {
7084  while (padding-- > 0 && (len < buf_size)) {
7085  if (flag & NK_ARG_FLAG_ZERO)
7086  buf[len++] = '0';
7087  else buf[len++] = ' ';
7088  }
7089  }
7090 
7091  /* copy string value representation into buffer */
7092  num_iter = number_buffer;
7093  if ((flag & NK_ARG_FLAG_PLUS) && (value >= 0) && (len < buf_size))
7094  buf[len++] = '+';
7095  else if ((flag & NK_ARG_FLAG_SPACE) && (value >= 0) && (len < buf_size))
7096  buf[len++] = ' ';
7097  while (*num_iter) {
7098  if (dot) frac_len++;
7099  if (len < buf_size)
7100  buf[len++] = *num_iter;
7101  if (*num_iter == '.') dot = 1;
7102  if (frac_len >= cur_precision) break;
7103  num_iter++;
7104  }
7105 
7106  /* fill number up to precision */
7107  while (frac_len < cur_precision) {
7108  if (!dot && len < buf_size) {
7109  buf[len++] = '.';
7110  dot = 1;
7111  }
7112  if (len < buf_size)
7113  buf[len++] = '0';
7114  frac_len++;
7115  }
7116 
7117  /* fill right padding up to width characters */
7118  if (flag & NK_ARG_FLAG_LEFT) {
7119  while ((padding-- > 0) && (len < buf_size))
7120  buf[len++] = ' ';
7121  }
7122  } else {
7123  /* Specifier not supported: g,G,e,E,p,z */
7124  NK_ASSERT(0 && "specifier is not supported!");
7125  return result;
7126  }
7127  }
7128  buf[(len >= buf_size)?(buf_size-1):len] = 0;
7129  result = (len >= buf_size)?-1:len;
7130  return result;
7131 }
7132 #endif
7133 NK_LIB int
7134 nk_strfmt(char *buf, int buf_size, const char *fmt, va_list args)
7135 {
7136  int result = -1;
7137  NK_ASSERT(buf);
7138  NK_ASSERT(buf_size);
7139  if (!buf || !buf_size || !fmt) return 0;
7140 #ifdef NK_INCLUDE_STANDARD_IO
7141  result = NK_VSNPRINTF(buf, (nk_size)buf_size, fmt, args);
7142  result = (result >= buf_size) ? -1: result;
7143  buf[buf_size-1] = 0;
7144 #else
7145  result = nk_vsnprintf(buf, buf_size, fmt, args);
7146 #endif
7147  return result;
7148 }
7149 #endif
7151 nk_murmur_hash(const void * key, int len, nk_hash seed)
7152 {
7153  /* 32-Bit MurmurHash3: https://code.google.com/p/smhasher/wiki/MurmurHash3*/
7154  #define NK_ROTL(x,r) ((x) << (r) | ((x) >> (32 - r)))
7155  union {const nk_uint *i; const nk_byte *b;} conv = {0};
7156  const nk_byte *data = (const nk_byte*)key;
7157  const int nblocks = len/4;
7158  nk_uint h1 = seed;
7159  const nk_uint c1 = 0xcc9e2d51;
7160  const nk_uint c2 = 0x1b873593;
7161  const nk_byte *tail;
7162  const nk_uint *blocks;
7163  nk_uint k1;
7164  int i;
7165 
7166  /* body */
7167  if (!key) return 0;
7168  conv.b = (data + nblocks*4);
7169  blocks = (const nk_uint*)conv.i;
7170  for (i = -nblocks; i; ++i) {
7171  k1 = blocks[i];
7172  k1 *= c1;
7173  k1 = NK_ROTL(k1,15);
7174  k1 *= c2;
7175 
7176  h1 ^= k1;
7177  h1 = NK_ROTL(h1,13);
7178  h1 = h1*5+0xe6546b64;
7179  }
7180 
7181  /* tail */
7182  tail = (const nk_byte*)(data + nblocks*4);
7183  k1 = 0;
7184  switch (len & 3) {
7185  case 3: k1 ^= (nk_uint)(tail[2] << 16); /* fallthrough */
7186  case 2: k1 ^= (nk_uint)(tail[1] << 8u); /* fallthrough */
7187  case 1: k1 ^= tail[0];
7188  k1 *= c1;
7189  k1 = NK_ROTL(k1,15);
7190  k1 *= c2;
7191  h1 ^= k1;
7192  break;
7193  default: break;
7194  }
7195 
7196  /* finalization */
7197  h1 ^= (nk_uint)len;
7198  /* fmix32 */
7199  h1 ^= h1 >> 16;
7200  h1 *= 0x85ebca6b;
7201  h1 ^= h1 >> 13;
7202  h1 *= 0xc2b2ae35;
7203  h1 ^= h1 >> 16;
7204 
7205  #undef NK_ROTL
7206  return h1;
7207 }
7208 #ifdef NK_INCLUDE_STANDARD_IO
7209 NK_LIB char*
7210 nk_file_load(const char* path, nk_size* siz, struct nk_allocator *alloc)
7211 {
7212  char *buf;
7213  FILE *fd;
7214  long ret;
7215 
7216  NK_ASSERT(path);
7217  NK_ASSERT(siz);
7218  NK_ASSERT(alloc);
7219  if (!path || !siz || !alloc)
7220  return 0;
7221 
7222  fd = fopen(path, "rb");
7223  if (!fd) return 0;
7224  fseek(fd, 0, SEEK_END);
7225  ret = ftell(fd);
7226  if (ret < 0) {
7227  fclose(fd);
7228  return 0;
7229  }
7230  *siz = (nk_size)ret;
7231  fseek(fd, 0, SEEK_SET);
7232  buf = (char*)alloc->alloc(alloc->userdata,0, *siz);
7233  NK_ASSERT(buf);
7234  if (!buf) {
7235  fclose(fd);
7236  return 0;
7237  }
7238  *siz = (nk_size)fread(buf, 1,*siz, fd);
7239  fclose(fd);
7240  return buf;
7241 }
7242 #endif
7243 NK_LIB int
7244 nk_text_clamp(const struct nk_user_font *font, const char *text,
7245  int text_len, float space, int *glyphs, float *text_width,
7246  nk_rune *sep_list, int sep_count)
7247 {
7248  int i = 0;
7249  int glyph_len = 0;
7250  float last_width = 0;
7251  nk_rune unicode = 0;
7252  float width = 0;
7253  int len = 0;
7254  int g = 0;
7255  float s;
7256 
7257  int sep_len = 0;
7258  int sep_g = 0;
7259  float sep_width = 0;
7260  sep_count = NK_MAX(sep_count,0);
7261 
7262  glyph_len = nk_utf_decode(text, &unicode, text_len);
7263  while (glyph_len && (width < space) && (len < text_len)) {
7264  len += glyph_len;
7265  s = font->width(font->userdata, font->height, text, len);
7266  for (i = 0; i < sep_count; ++i) {
7267  if (unicode != sep_list[i]) continue;
7268  sep_width = last_width = width;
7269  sep_g = g+1;
7270  sep_len = len;
7271  break;
7272  }
7273  if (i == sep_count){
7274  last_width = sep_width = width;
7275  sep_g = g+1;
7276  }
7277  width = s;
7278  glyph_len = nk_utf_decode(&text[len], &unicode, text_len - len);
7279  g++;
7280  }
7281  if (len >= text_len) {
7282  *glyphs = g;
7283  *text_width = last_width;
7284  return len;
7285  } else {
7286  *glyphs = sep_g;
7287  *text_width = sep_width;
7288  return (!sep_len) ? len: sep_len;
7289  }
7290 }
7291 NK_LIB struct nk_vec2
7292 nk_text_calculate_text_bounds(const struct nk_user_font *font,
7293  const char *begin, int byte_len, float row_height, const char **remaining,
7294  struct nk_vec2 *out_offset, int *glyphs, int op)
7295 {
7296  float line_height = row_height;
7297  struct nk_vec2 text_size = nk_vec2(0,0);
7298  float line_width = 0.0f;
7299 
7300  float glyph_width;
7301  int glyph_len = 0;
7302  nk_rune unicode = 0;
7303  int text_len = 0;
7304  if (!begin || byte_len <= 0 || !font)
7305  return nk_vec2(0,row_height);
7306 
7307  glyph_len = nk_utf_decode(begin, &unicode, byte_len);
7308  if (!glyph_len) return text_size;
7309  glyph_width = font->width(font->userdata, font->height, begin, glyph_len);
7310 
7311  *glyphs = 0;
7312  while ((text_len < byte_len) && glyph_len) {
7313  if (unicode == '\n') {
7314  text_size.x = NK_MAX(text_size.x, line_width);
7315  text_size.y += line_height;
7316  line_width = 0;
7317  *glyphs+=1;
7318  if (op == NK_STOP_ON_NEW_LINE)
7319  break;
7320 
7321  text_len++;
7322  glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
7323  continue;
7324  }
7325 
7326  if (unicode == '\r') {
7327  text_len++;
7328  *glyphs+=1;
7329  glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
7330  continue;
7331  }
7332 
7333  *glyphs = *glyphs + 1;
7334  text_len += glyph_len;
7335  line_width += (float)glyph_width;
7336  glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
7337  glyph_width = font->width(font->userdata, font->height, begin+text_len, glyph_len);
7338  continue;
7339  }
7340 
7341  if (text_size.x < line_width)
7342  text_size.x = line_width;
7343  if (out_offset)
7344  *out_offset = nk_vec2(line_width, text_size.y + line_height);
7345  if (line_width > 0 || text_size.y == 0.0f)
7346  text_size.y += line_height;
7347  if (remaining)
7348  *remaining = begin+text_len;
7349  return text_size;
7350 }
7351 
7352 
7353 
7354 
7355 
7356 /* ==============================================================
7357  *
7358  * COLOR
7359  *
7360  * ===============================================================*/
7361 NK_INTERN int
7362 nk_parse_hex(const char *p, int length)
7363 {
7364  int i = 0;
7365  int len = 0;
7366  while (len < length) {
7367  i <<= 4;
7368  if (p[len] >= 'a' && p[len] <= 'f')
7369  i += ((p[len] - 'a') + 10);
7370  else if (p[len] >= 'A' && p[len] <= 'F')
7371  i += ((p[len] - 'A') + 10);
7372  else i += (p[len] - '0');
7373  len++;
7374  }
7375  return i;
7376 }
7377 NK_API struct nk_color
7378 nk_rgba(int r, int g, int b, int a)
7379 {
7380  struct nk_color ret;
7381  ret.r = (nk_byte)NK_CLAMP(0, r, 255);
7382  ret.g = (nk_byte)NK_CLAMP(0, g, 255);
7383  ret.b = (nk_byte)NK_CLAMP(0, b, 255);
7384  ret.a = (nk_byte)NK_CLAMP(0, a, 255);
7385  return ret;
7386 }
7387 NK_API struct nk_color
7388 nk_rgb_hex(const char *rgb)
7389 {
7390  struct nk_color col;
7391  const char *c = rgb;
7392  if (*c == '#') c++;
7393  col.r = (nk_byte)nk_parse_hex(c, 2);
7394  col.g = (nk_byte)nk_parse_hex(c+2, 2);
7395  col.b = (nk_byte)nk_parse_hex(c+4, 2);
7396  col.a = 255;
7397  return col;
7398 }
7399 NK_API struct nk_color
7400 nk_rgba_hex(const char *rgb)
7401 {
7402  struct nk_color col;
7403  const char *c = rgb;
7404  if (*c == '#') c++;
7405  col.r = (nk_byte)nk_parse_hex(c, 2);
7406  col.g = (nk_byte)nk_parse_hex(c+2, 2);
7407  col.b = (nk_byte)nk_parse_hex(c+4, 2);
7408  col.a = (nk_byte)nk_parse_hex(c+6, 2);
7409  return col;
7410 }
7411 NK_API void
7412 nk_color_hex_rgba(char *output, struct nk_color col)
7413 {
7414  #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i))
7415  output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4);
7416  output[1] = (char)NK_TO_HEX((col.r & 0x0F));
7417  output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4);
7418  output[3] = (char)NK_TO_HEX((col.g & 0x0F));
7419  output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4);
7420  output[5] = (char)NK_TO_HEX((col.b & 0x0F));
7421  output[6] = (char)NK_TO_HEX((col.a & 0xF0) >> 4);
7422  output[7] = (char)NK_TO_HEX((col.a & 0x0F));
7423  output[8] = '\0';
7424  #undef NK_TO_HEX
7425 }
7426 NK_API void
7427 nk_color_hex_rgb(char *output, struct nk_color col)
7428 {
7429  #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i))
7430  output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4);
7431  output[1] = (char)NK_TO_HEX((col.r & 0x0F));
7432  output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4);
7433  output[3] = (char)NK_TO_HEX((col.g & 0x0F));
7434  output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4);
7435  output[5] = (char)NK_TO_HEX((col.b & 0x0F));
7436  output[6] = '\0';
7437  #undef NK_TO_HEX
7438 }
7439 NK_API struct nk_color
7440 nk_rgba_iv(const int *c)
7441 {
7442  return nk_rgba(c[0], c[1], c[2], c[3]);
7443 }
7444 NK_API struct nk_color
7445 nk_rgba_bv(const nk_byte *c)
7446 {
7447  return nk_rgba(c[0], c[1], c[2], c[3]);
7448 }
7449 NK_API struct nk_color
7450 nk_rgb(int r, int g, int b)
7451 {
7452  struct nk_color ret;
7453  ret.r = (nk_byte)NK_CLAMP(0, r, 255);
7454  ret.g = (nk_byte)NK_CLAMP(0, g, 255);
7455  ret.b = (nk_byte)NK_CLAMP(0, b, 255);
7456  ret.a = (nk_byte)255;
7457  return ret;
7458 }
7459 NK_API struct nk_color
7460 nk_rgb_iv(const int *c)
7461 {
7462  return nk_rgb(c[0], c[1], c[2]);
7463 }
7464 NK_API struct nk_color
7465 nk_rgb_bv(const nk_byte* c)
7466 {
7467  return nk_rgb(c[0], c[1], c[2]);
7468 }
7469 NK_API struct nk_color
7470 nk_rgba_u32(nk_uint in)
7471 {
7472  struct nk_color ret;
7473  ret.r = (in & 0xFF);
7474  ret.g = ((in >> 8) & 0xFF);
7475  ret.b = ((in >> 16) & 0xFF);
7476  ret.a = (nk_byte)((in >> 24) & 0xFF);
7477  return ret;
7478 }
7479 NK_API struct nk_color
7480 nk_rgba_f(float r, float g, float b, float a)
7481 {
7482  struct nk_color ret;
7483  ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f);
7484  ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f);
7485  ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f);
7486  ret.a = (nk_byte)(NK_SATURATE(a) * 255.0f);
7487  return ret;
7488 }
7489 NK_API struct nk_color
7490 nk_rgba_fv(const float *c)
7491 {
7492  return nk_rgba_f(c[0], c[1], c[2], c[3]);
7493 }
7494 NK_API struct nk_color
7495 nk_rgba_cf(struct nk_colorf c)
7496 {
7497  return nk_rgba_f(c.r, c.g, c.b, c.a);
7498 }
7499 NK_API struct nk_color
7500 nk_rgb_f(float r, float g, float b)
7501 {
7502  struct nk_color ret;
7503  ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f);
7504  ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f);
7505  ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f);
7506  ret.a = 255;
7507  return ret;
7508 }
7509 NK_API struct nk_color
7510 nk_rgb_fv(const float *c)
7511 {
7512  return nk_rgb_f(c[0], c[1], c[2]);
7513 }
7514 NK_API struct nk_color
7515 nk_rgb_cf(struct nk_colorf c)
7516 {
7517  return nk_rgb_f(c.r, c.g, c.b);
7518 }
7519 NK_API struct nk_color
7520 nk_hsv(int h, int s, int v)
7521 {
7522  return nk_hsva(h, s, v, 255);
7523 }
7524 NK_API struct nk_color
7525 nk_hsv_iv(const int *c)
7526 {
7527  return nk_hsv(c[0], c[1], c[2]);
7528 }
7529 NK_API struct nk_color
7530 nk_hsv_bv(const nk_byte *c)
7531 {
7532  return nk_hsv(c[0], c[1], c[2]);
7533 }
7534 NK_API struct nk_color
7535 nk_hsv_f(float h, float s, float v)
7536 {
7537  return nk_hsva_f(h, s, v, 1.0f);
7538 }
7539 NK_API struct nk_color
7540 nk_hsv_fv(const float *c)
7541 {
7542  return nk_hsv_f(c[0], c[1], c[2]);
7543 }
7544 NK_API struct nk_color
7545 nk_hsva(int h, int s, int v, int a)
7546 {
7547  float hf = ((float)NK_CLAMP(0, h, 255)) / 255.0f;
7548  float sf = ((float)NK_CLAMP(0, s, 255)) / 255.0f;
7549  float vf = ((float)NK_CLAMP(0, v, 255)) / 255.0f;
7550  float af = ((float)NK_CLAMP(0, a, 255)) / 255.0f;
7551  return nk_hsva_f(hf, sf, vf, af);
7552 }
7553 NK_API struct nk_color
7554 nk_hsva_iv(const int *c)
7555 {
7556  return nk_hsva(c[0], c[1], c[2], c[3]);
7557 }
7558 NK_API struct nk_color
7559 nk_hsva_bv(const nk_byte *c)
7560 {
7561  return nk_hsva(c[0], c[1], c[2], c[3]);
7562 }
7563 NK_API struct nk_colorf
7564 nk_hsva_colorf(float h, float s, float v, float a)
7565 {
7566  int i;
7567  float p, q, t, f;
7568  struct nk_colorf out = {0,0,0,0};
7569  if (s <= 0.0f) {
7570  out.r = v; out.g = v; out.b = v; out.a = a;
7571  return out;
7572  }
7573  h = h / (60.0f/360.0f);
7574  i = (int)h;
7575  f = h - (float)i;
7576  p = v * (1.0f - s);
7577  q = v * (1.0f - (s * f));
7578  t = v * (1.0f - s * (1.0f - f));
7579 
7580  switch (i) {
7581  case 0: default: out.r = v; out.g = t; out.b = p; break;
7582  case 1: out.r = q; out.g = v; out.b = p; break;
7583  case 2: out.r = p; out.g = v; out.b = t; break;
7584  case 3: out.r = p; out.g = q; out.b = v; break;
7585  case 4: out.r = t; out.g = p; out.b = v; break;
7586  case 5: out.r = v; out.g = p; out.b = q; break;}
7587  out.a = a;
7588  return out;
7589 }
7590 NK_API struct nk_colorf
7591 nk_hsva_colorfv(float *c)
7592 {
7593  return nk_hsva_colorf(c[0], c[1], c[2], c[3]);
7594 }
7595 NK_API struct nk_color
7596 nk_hsva_f(float h, float s, float v, float a)
7597 {
7598  struct nk_colorf c = nk_hsva_colorf(h, s, v, a);
7599  return nk_rgba_f(c.r, c.g, c.b, c.a);
7600 }
7601 NK_API struct nk_color
7602 nk_hsva_fv(const float *c)
7603 {
7604  return nk_hsva_f(c[0], c[1], c[2], c[3]);
7605 }
7607 nk_color_u32(struct nk_color in)
7608 {
7609  nk_uint out = (nk_uint)in.r;
7610  out |= ((nk_uint)in.g << 8);
7611  out |= ((nk_uint)in.b << 16);
7612  out |= ((nk_uint)in.a << 24);
7613  return out;
7614 }
7615 NK_API void
7616 nk_color_f(float *r, float *g, float *b, float *a, struct nk_color in)
7617 {
7618  NK_STORAGE const float s = 1.0f/255.0f;
7619  *r = (float)in.r * s;
7620  *g = (float)in.g * s;
7621  *b = (float)in.b * s;
7622  *a = (float)in.a * s;
7623 }
7624 NK_API void
7625 nk_color_fv(float *c, struct nk_color in)
7626 {
7627  nk_color_f(&c[0], &c[1], &c[2], &c[3], in);
7628 }
7629 NK_API struct nk_colorf
7630 nk_color_cf(struct nk_color in)
7631 {
7632  struct nk_colorf o;
7633  nk_color_f(&o.r, &o.g, &o.b, &o.a, in);
7634  return o;
7635 }
7636 NK_API void
7637 nk_color_d(double *r, double *g, double *b, double *a, struct nk_color in)
7638 {
7639  NK_STORAGE const double s = 1.0/255.0;
7640  *r = (double)in.r * s;
7641  *g = (double)in.g * s;
7642  *b = (double)in.b * s;
7643  *a = (double)in.a * s;
7644 }
7645 NK_API void
7646 nk_color_dv(double *c, struct nk_color in)
7647 {
7648  nk_color_d(&c[0], &c[1], &c[2], &c[3], in);
7649 }
7650 NK_API void
7651 nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color in)
7652 {
7653  float a;
7654  nk_color_hsva_f(out_h, out_s, out_v, &a, in);
7655 }
7656 NK_API void
7657 nk_color_hsv_fv(float *out, struct nk_color in)
7658 {
7659  float a;
7660  nk_color_hsva_f(&out[0], &out[1], &out[2], &a, in);
7661 }
7662 NK_API void
7663 nk_colorf_hsva_f(float *out_h, float *out_s,
7664  float *out_v, float *out_a, struct nk_colorf in)
7665 {
7666  float chroma;
7667  float K = 0.0f;
7668  if (in.g < in.b) {
7669  const float t = in.g; in.g = in.b; in.b = t;
7670  K = -1.f;
7671  }
7672  if (in.r < in.g) {
7673  const float t = in.r; in.r = in.g; in.g = t;
7674  K = -2.f/6.0f - K;
7675  }
7676  chroma = in.r - ((in.g < in.b) ? in.g: in.b);
7677  *out_h = NK_ABS(K + (in.g - in.b)/(6.0f * chroma + 1e-20f));
7678  *out_s = chroma / (in.r + 1e-20f);
7679  *out_v = in.r;
7680  *out_a = in.a;
7681 
7682 }
7683 NK_API void
7684 nk_colorf_hsva_fv(float *hsva, struct nk_colorf in)
7685 {
7686  nk_colorf_hsva_f(&hsva[0], &hsva[1], &hsva[2], &hsva[3], in);
7687 }
7688 NK_API void
7689 nk_color_hsva_f(float *out_h, float *out_s,
7690  float *out_v, float *out_a, struct nk_color in)
7691 {
7692  struct nk_colorf col;
7693  nk_color_f(&col.r,&col.g,&col.b,&col.a, in);
7694  nk_colorf_hsva_f(out_h, out_s, out_v, out_a, col);
7695 }
7696 NK_API void
7697 nk_color_hsva_fv(float *out, struct nk_color in)
7698 {
7699  nk_color_hsva_f(&out[0], &out[1], &out[2], &out[3], in);
7700 }
7701 NK_API void
7702 nk_color_hsva_i(int *out_h, int *out_s, int *out_v,
7703  int *out_a, struct nk_color in)
7704 {
7705  float h,s,v,a;
7706  nk_color_hsva_f(&h, &s, &v, &a, in);
7707  *out_h = (nk_byte)(h * 255.0f);
7708  *out_s = (nk_byte)(s * 255.0f);
7709  *out_v = (nk_byte)(v * 255.0f);
7710  *out_a = (nk_byte)(a * 255.0f);
7711 }
7712 NK_API void
7713 nk_color_hsva_iv(int *out, struct nk_color in)
7714 {
7715  nk_color_hsva_i(&out[0], &out[1], &out[2], &out[3], in);
7716 }
7717 NK_API void
7718 nk_color_hsva_bv(nk_byte *out, struct nk_color in)
7719 {
7720  int tmp[4];
7721  nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
7722  out[0] = (nk_byte)tmp[0];
7723  out[1] = (nk_byte)tmp[1];
7724  out[2] = (nk_byte)tmp[2];
7725  out[3] = (nk_byte)tmp[3];
7726 }
7727 NK_API void
7728 nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color in)
7729 {
7730  int tmp[4];
7731  nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
7732  *h = (nk_byte)tmp[0];
7733  *s = (nk_byte)tmp[1];
7734  *v = (nk_byte)tmp[2];
7735  *a = (nk_byte)tmp[3];
7736 }
7737 NK_API void
7738 nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color in)
7739 {
7740  int a;
7741  nk_color_hsva_i(out_h, out_s, out_v, &a, in);
7742 }
7743 NK_API void
7744 nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color in)
7745 {
7746  int tmp[4];
7747  nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
7748  *out_h = (nk_byte)tmp[0];
7749  *out_s = (nk_byte)tmp[1];
7750  *out_v = (nk_byte)tmp[2];
7751 }
7752 NK_API void
7753 nk_color_hsv_iv(int *out, struct nk_color in)
7754 {
7755  nk_color_hsv_i(&out[0], &out[1], &out[2], in);
7756 }
7757 NK_API void
7758 nk_color_hsv_bv(nk_byte *out, struct nk_color in)
7759 {
7760  int tmp[4];
7761  nk_color_hsv_i(&tmp[0], &tmp[1], &tmp[2], in);
7762  out[0] = (nk_byte)tmp[0];
7763  out[1] = (nk_byte)tmp[1];
7764  out[2] = (nk_byte)tmp[2];
7765 }
7766 
7767 
7768 
7769 
7770 
7771 /* ===============================================================
7772  *
7773  * UTF-8
7774  *
7775  * ===============================================================*/
7776 NK_GLOBAL const nk_byte nk_utfbyte[NK_UTF_SIZE+1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
7777 NK_GLOBAL const nk_byte nk_utfmask[NK_UTF_SIZE+1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
7778 NK_GLOBAL const nk_uint nk_utfmin[NK_UTF_SIZE+1] = {0, 0, 0x80, 0x800, 0x10000};
7779 NK_GLOBAL const nk_uint nk_utfmax[NK_UTF_SIZE+1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
7780 
7781 NK_INTERN int
7782 nk_utf_validate(nk_rune *u, int i)
7783 {
7784  NK_ASSERT(u);
7785  if (!u) return 0;
7786  if (!NK_BETWEEN(*u, nk_utfmin[i], nk_utfmax[i]) ||
7787  NK_BETWEEN(*u, 0xD800, 0xDFFF))
7788  *u = NK_UTF_INVALID;
7789  for (i = 1; *u > nk_utfmax[i]; ++i);
7790  return i;
7791 }
7793 nk_utf_decode_byte(char c, int *i)
7794 {
7795  NK_ASSERT(i);
7796  if (!i) return 0;
7797  for(*i = 0; *i < (int)NK_LEN(nk_utfmask); ++(*i)) {
7798  if (((nk_byte)c & nk_utfmask[*i]) == nk_utfbyte[*i])
7799  return (nk_byte)(c & ~nk_utfmask[*i]);
7800  }
7801  return 0;
7802 }
7803 NK_API int
7804 nk_utf_decode(const char *c, nk_rune *u, int clen)
7805 {
7806  int i, j, len, type=0;
7807  nk_rune udecoded;
7808 
7809  NK_ASSERT(c);
7810  NK_ASSERT(u);
7811 
7812  if (!c || !u) return 0;
7813  if (!clen) return 0;
7814  *u = NK_UTF_INVALID;
7815 
7816  udecoded = nk_utf_decode_byte(c[0], &len);
7817  if (!NK_BETWEEN(len, 1, NK_UTF_SIZE))
7818  return 1;
7819 
7820  for (i = 1, j = 1; i < clen && j < len; ++i, ++j) {
7821  udecoded = (udecoded << 6) | nk_utf_decode_byte(c[i], &type);
7822  if (type != 0)
7823  return j;
7824  }
7825  if (j < len)
7826  return 0;
7827  *u = udecoded;
7828  nk_utf_validate(u, len);
7829  return len;
7830 }
7831 NK_INTERN char
7832 nk_utf_encode_byte(nk_rune u, int i)
7833 {
7834  return (char)((nk_utfbyte[i]) | ((nk_byte)u & ~nk_utfmask[i]));
7835 }
7836 NK_API int
7837 nk_utf_encode(nk_rune u, char *c, int clen)
7838 {
7839  int len, i;
7840  len = nk_utf_validate(&u, 0);
7841  if (clen < len || !len || len > NK_UTF_SIZE)
7842  return 0;
7843 
7844  for (i = len - 1; i != 0; --i) {
7845  c[i] = nk_utf_encode_byte(u, 0);
7846  u >>= 6;
7847  }
7848  c[0] = nk_utf_encode_byte(u, len);
7849  return len;
7850 }
7851 NK_API int
7852 nk_utf_len(const char *str, int len)
7853 {
7854  const char *text;
7855  int glyphs = 0;
7856  int text_len;
7857  int glyph_len;
7858  int src_len = 0;
7859  nk_rune unicode;
7860 
7861  NK_ASSERT(str);
7862  if (!str || !len) return 0;
7863 
7864  text = str;
7865  text_len = len;
7866  glyph_len = nk_utf_decode(text, &unicode, text_len);
7867  while (glyph_len && src_len < len) {
7868  glyphs++;
7869  src_len = src_len + glyph_len;
7870  glyph_len = nk_utf_decode(text + src_len, &unicode, text_len - src_len);
7871  }
7872  return glyphs;
7873 }
7874 NK_API const char*
7875 nk_utf_at(const char *buffer, int length, int index,
7876  nk_rune *unicode, int *len)
7877 {
7878  int i = 0;
7879  int src_len = 0;
7880  int glyph_len = 0;
7881  const char *text;
7882  int text_len;
7883 
7884  NK_ASSERT(buffer);
7885  NK_ASSERT(unicode);
7886  NK_ASSERT(len);
7887 
7888  if (!buffer || !unicode || !len) return 0;
7889  if (index < 0) {
7890  *unicode = NK_UTF_INVALID;
7891  *len = 0;
7892  return 0;
7893  }
7894 
7895  text = buffer;
7896  text_len = length;
7897  glyph_len = nk_utf_decode(text, unicode, text_len);
7898  while (glyph_len) {
7899  if (i == index) {
7900  *len = glyph_len;
7901  break;
7902  }
7903 
7904  i++;
7905  src_len = src_len + glyph_len;
7906  glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
7907  }
7908  if (i != index) return 0;
7909  return buffer + src_len;
7910 }
7911 
7912 
7913 
7914 
7915 
7916 /* ==============================================================
7917  *
7918  * BUFFER
7919  *
7920  * ===============================================================*/
7921 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
7922 NK_LIB void*
7923 nk_malloc(nk_handle unused, void *old,nk_size size)
7924 {
7925  NK_UNUSED(unused);
7926  NK_UNUSED(old);
7927  return malloc(size);
7928 }
7929 NK_LIB void
7930 nk_mfree(nk_handle unused, void *ptr)
7931 {
7932  NK_UNUSED(unused);
7933  free(ptr);
7934 }
7935 NK_API void
7936 nk_buffer_init_default(struct nk_buffer *buffer)
7937 {
7938  struct nk_allocator alloc;
7939  alloc.userdata.ptr = 0;
7940  alloc.alloc = nk_malloc;
7941  alloc.free = nk_mfree;
7942  nk_buffer_init(buffer, &alloc, NK_BUFFER_DEFAULT_INITIAL_SIZE);
7943 }
7944 #endif
7945 
7946 NK_API void
7947 nk_buffer_init(struct nk_buffer *b, const struct nk_allocator *a,
7948  nk_size initial_size)
7949 {
7950  NK_ASSERT(b);
7951  NK_ASSERT(a);
7952  NK_ASSERT(initial_size);
7953  if (!b || !a || !initial_size) return;
7954 
7955  nk_zero(b, sizeof(*b));
7956  b->type = NK_BUFFER_DYNAMIC;
7957  b->memory.ptr = a->alloc(a->userdata,0, initial_size);
7958  b->memory.size = initial_size;
7959  b->size = initial_size;
7960  b->grow_factor = 2.0f;
7961  b->pool = *a;
7962 }
7963 NK_API void
7964 nk_buffer_init_fixed(struct nk_buffer *b, void *m, nk_size size)
7965 {
7966  NK_ASSERT(b);
7967  NK_ASSERT(m);
7968  NK_ASSERT(size);
7969  if (!b || !m || !size) return;
7970 
7971  nk_zero(b, sizeof(*b));
7972  b->type = NK_BUFFER_FIXED;
7973  b->memory.ptr = m;
7974  b->memory.size = size;
7975  b->size = size;
7976 }
7977 NK_LIB void*
7978 nk_buffer_align(void *unaligned,
7979  nk_size align, nk_size *alignment,
7980  enum nk_buffer_allocation_type type)
7981 {
7982  void *memory = 0;
7983  switch (type) {
7984  default:
7985  case NK_BUFFER_MAX:
7986  case NK_BUFFER_FRONT:
7987  if (align) {
7988  memory = NK_ALIGN_PTR(unaligned, align);
7989  *alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned);
7990  } else {
7991  memory = unaligned;
7992  *alignment = 0;
7993  }
7994  break;
7995  case NK_BUFFER_BACK:
7996  if (align) {
7997  memory = NK_ALIGN_PTR_BACK(unaligned, align);
7998  *alignment = (nk_size)((nk_byte*)unaligned - (nk_byte*)memory);
7999  } else {
8000  memory = unaligned;
8001  *alignment = 0;
8002  }
8003  break;
8004  }
8005  return memory;
8006 }
8007 NK_LIB void*
8008 nk_buffer_realloc(struct nk_buffer *b, nk_size capacity, nk_size *size)
8009 {
8010  void *temp;
8011  nk_size buffer_size;
8012 
8013  NK_ASSERT(b);
8014  NK_ASSERT(size);
8015  if (!b || !size || !b->pool.alloc || !b->pool.free)
8016  return 0;
8017 
8018  buffer_size = b->memory.size;
8019  temp = b->pool.alloc(b->pool.userdata, b->memory.ptr, capacity);
8020  NK_ASSERT(temp);
8021  if (!temp) return 0;
8022 
8023  *size = capacity;
8024  if (temp != b->memory.ptr) {
8025  NK_MEMCPY(temp, b->memory.ptr, buffer_size);
8026  b->pool.free(b->pool.userdata, b->memory.ptr);
8027  }
8028 
8029  if (b->size == buffer_size) {
8030  /* no back buffer so just set correct size */
8031  b->size = capacity;
8032  return temp;
8033  } else {
8034  /* copy back buffer to the end of the new buffer */
8035  void *dst, *src;
8036  nk_size back_size;
8037  back_size = buffer_size - b->size;
8038  dst = nk_ptr_add(void, temp, capacity - back_size);
8039  src = nk_ptr_add(void, temp, b->size);
8040  NK_MEMCPY(dst, src, back_size);
8041  b->size = capacity - back_size;
8042  }
8043  return temp;
8044 }
8045 NK_LIB void*
8046 nk_buffer_alloc(struct nk_buffer *b, enum nk_buffer_allocation_type type,
8047  nk_size size, nk_size align)
8048 {
8049  int full;
8050  nk_size alignment;
8051  void *unaligned;
8052  void *memory;
8053 
8054  NK_ASSERT(b);
8055  NK_ASSERT(size);
8056  if (!b || !size) return 0;
8057  b->needed += size;
8058 
8059  /* calculate total size with needed alignment + size */
8060  if (type == NK_BUFFER_FRONT)
8061  unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated);
8062  else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size);
8063  memory = nk_buffer_align(unaligned, align, &alignment, type);
8064 
8065  /* check if buffer has enough memory*/
8066  if (type == NK_BUFFER_FRONT)
8067  full = ((b->allocated + size + alignment) > b->size);
8068  else full = ((b->size - NK_MIN(b->size,(size + alignment))) <= b->allocated);
8069 
8070  if (full) {
8071  nk_size capacity;
8072  if (b->type != NK_BUFFER_DYNAMIC)
8073  return 0;
8074  NK_ASSERT(b->pool.alloc && b->pool.free);
8075  if (b->type != NK_BUFFER_DYNAMIC || !b->pool.alloc || !b->pool.free)
8076  return 0;
8077 
8078  /* buffer is full so allocate bigger buffer if dynamic */
8079  capacity = (nk_size)((float)b->memory.size * b->grow_factor);
8080  capacity = NK_MAX(capacity, nk_round_up_pow2((nk_uint)(b->allocated + size)));
8081  b->memory.ptr = nk_buffer_realloc(b, capacity, &b->memory.size);
8082  if (!b->memory.ptr) return 0;
8083 
8084  /* align newly allocated pointer */
8085  if (type == NK_BUFFER_FRONT)
8086  unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated);
8087  else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size);
8088  memory = nk_buffer_align(unaligned, align, &alignment, type);
8089  }
8090  if (type == NK_BUFFER_FRONT)
8091  b->allocated += size + alignment;
8092  else b->size -= (size + alignment);
8093  b->needed += alignment;
8094  b->calls++;
8095  return memory;
8096 }
8097 NK_API void
8099  const void *memory, nk_size size, nk_size align)
8100 {
8101  void *mem = nk_buffer_alloc(b, type, size, align);
8102  if (!mem) return;
8103  NK_MEMCPY(mem, memory, size);
8104 }
8105 NK_API void
8106 nk_buffer_mark(struct nk_buffer *buffer, enum nk_buffer_allocation_type type)
8107 {
8108  NK_ASSERT(buffer);
8109  if (!buffer) return;
8110  buffer->marker[type].active = nk_true;
8111  if (type == NK_BUFFER_BACK)
8112  buffer->marker[type].offset = buffer->size;
8113  else buffer->marker[type].offset = buffer->allocated;
8114 }
8115 NK_API void
8116 nk_buffer_reset(struct nk_buffer *buffer, enum nk_buffer_allocation_type type)
8117 {
8118  NK_ASSERT(buffer);
8119  if (!buffer) return;
8120  if (type == NK_BUFFER_BACK) {
8121  /* reset back buffer either back to marker or empty */
8122  buffer->needed -= (buffer->memory.size - buffer->marker[type].offset);
8123  if (buffer->marker[type].active)
8124  buffer->size = buffer->marker[type].offset;
8125  else buffer->size = buffer->memory.size;
8126  buffer->marker[type].active = nk_false;
8127  } else {
8128  /* reset front buffer either back to back marker or empty */
8129  buffer->needed -= (buffer->allocated - buffer->marker[type].offset);
8130  if (buffer->marker[type].active)
8131  buffer->allocated = buffer->marker[type].offset;
8132  else buffer->allocated = 0;
8133  buffer->marker[type].active = nk_false;
8134  }
8135 }
8136 NK_API void
8137 nk_buffer_clear(struct nk_buffer *b)
8138 {
8139  NK_ASSERT(b);
8140  if (!b) return;
8141  b->allocated = 0;
8142  b->size = b->memory.size;
8143  b->calls = 0;
8144  b->needed = 0;
8145 }
8146 NK_API void
8147 nk_buffer_free(struct nk_buffer *b)
8148 {
8149  NK_ASSERT(b);
8150  if (!b || !b->memory.ptr) return;
8151  if (b->type == NK_BUFFER_FIXED) return;
8152  if (!b->pool.free) return;
8153  NK_ASSERT(b->pool.free);
8154  b->pool.free(b->pool.userdata, b->memory.ptr);
8155 }
8156 NK_API void
8157 nk_buffer_info(struct nk_memory_status *s, struct nk_buffer *b)
8158 {
8159  NK_ASSERT(b);
8160  NK_ASSERT(s);
8161  if (!s || !b) return;
8162  s->allocated = b->allocated;
8163  s->size = b->memory.size;
8164  s->needed = b->needed;
8165  s->memory = b->memory.ptr;
8166  s->calls = b->calls;
8167 }
8168 NK_API void*
8169 nk_buffer_memory(struct nk_buffer *buffer)
8170 {
8171  NK_ASSERT(buffer);
8172  if (!buffer) return 0;
8173  return buffer->memory.ptr;
8174 }
8175 NK_API const void*
8176 nk_buffer_memory_const(const struct nk_buffer *buffer)
8177 {
8178  NK_ASSERT(buffer);
8179  if (!buffer) return 0;
8180  return buffer->memory.ptr;
8181 }
8183 nk_buffer_total(struct nk_buffer *buffer)
8184 {
8185  NK_ASSERT(buffer);
8186  if (!buffer) return 0;
8187  return buffer->memory.size;
8188 }
8189 
8190 
8191 
8192 
8193 
8194 /* ===============================================================
8195  *
8196  * STRING
8197  *
8198  * ===============================================================*/
8199 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
8200 NK_API void
8201 nk_str_init_default(struct nk_str *str)
8202 {
8203  struct nk_allocator alloc;
8204  alloc.userdata.ptr = 0;
8205  alloc.alloc = nk_malloc;
8206  alloc.free = nk_mfree;
8207  nk_buffer_init(&str->buffer, &alloc, 32);
8208  str->len = 0;
8209 }
8210 #endif
8211 
8212 NK_API void
8213 nk_str_init(struct nk_str *str, const struct nk_allocator *alloc, nk_size size)
8214 {
8215  nk_buffer_init(&str->buffer, alloc, size);
8216  str->len = 0;
8217 }
8218 NK_API void
8219 nk_str_init_fixed(struct nk_str *str, void *memory, nk_size size)
8220 {
8221  nk_buffer_init_fixed(&str->buffer, memory, size);
8222  str->len = 0;
8223 }
8224 NK_API int
8225 nk_str_append_text_char(struct nk_str *s, const char *str, int len)
8226 {
8227  char *mem;
8228  NK_ASSERT(s);
8229  NK_ASSERT(str);
8230  if (!s || !str || !len) return 0;
8231  mem = (char*)nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0);
8232  if (!mem) return 0;
8233  NK_MEMCPY(mem, str, (nk_size)len * sizeof(char));
8234  s->len += nk_utf_len(str, len);
8235  return len;
8236 }
8237 NK_API int
8238 nk_str_append_str_char(struct nk_str *s, const char *str)
8239 {
8240  return nk_str_append_text_char(s, str, nk_strlen(str));
8241 }
8242 NK_API int
8243 nk_str_append_text_utf8(struct nk_str *str, const char *text, int len)
8244 {
8245  int i = 0;
8246  int byte_len = 0;
8247  nk_rune unicode;
8248  if (!str || !text || !len) return 0;
8249  for (i = 0; i < len; ++i)
8250  byte_len += nk_utf_decode(text+byte_len, &unicode, 4);
8251  nk_str_append_text_char(str, text, byte_len);
8252  return len;
8253 }
8254 NK_API int
8255 nk_str_append_str_utf8(struct nk_str *str, const char *text)
8256 {
8257  int runes = 0;
8258  int byte_len = 0;
8259  int num_runes = 0;
8260  int glyph_len = 0;
8261  nk_rune unicode;
8262  if (!str || !text) return 0;
8263 
8264  glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4);
8265  while (unicode != '\0' && glyph_len) {
8266  glyph_len = nk_utf_decode(text+byte_len, &unicode, 4);
8267  byte_len += glyph_len;
8268  num_runes++;
8269  }
8270  nk_str_append_text_char(str, text, byte_len);
8271  return runes;
8272 }
8273 NK_API int
8274 nk_str_append_text_runes(struct nk_str *str, const nk_rune *text, int len)
8275 {
8276  int i = 0;
8277  int byte_len = 0;
8278  nk_glyph glyph;
8279 
8280  NK_ASSERT(str);
8281  if (!str || !text || !len) return 0;
8282  for (i = 0; i < len; ++i) {
8283  byte_len = nk_utf_encode(text[i], glyph, NK_UTF_SIZE);
8284  if (!byte_len) break;
8285  nk_str_append_text_char(str, glyph, byte_len);
8286  }
8287  return len;
8288 }
8289 NK_API int
8290 nk_str_append_str_runes(struct nk_str *str, const nk_rune *runes)
8291 {
8292  int i = 0;
8293  nk_glyph glyph;
8294  int byte_len;
8295  NK_ASSERT(str);
8296  if (!str || !runes) return 0;
8297  while (runes[i] != '\0') {
8298  byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
8299  nk_str_append_text_char(str, glyph, byte_len);
8300  i++;
8301  }
8302  return i;
8303 }
8304 NK_API int
8305 nk_str_insert_at_char(struct nk_str *s, int pos, const char *str, int len)
8306 {
8307  int i;
8308  void *mem;
8309  char *src;
8310  char *dst;
8311 
8312  int copylen;
8313  NK_ASSERT(s);
8314  NK_ASSERT(str);
8315  NK_ASSERT(len >= 0);
8316  if (!s || !str || !len || (nk_size)pos > s->buffer.allocated) return 0;
8317  if ((s->buffer.allocated + (nk_size)len >= s->buffer.memory.size) &&
8318  (s->buffer.type == NK_BUFFER_FIXED)) return 0;
8319 
8320  copylen = (int)s->buffer.allocated - pos;
8321  if (!copylen) {
8322  nk_str_append_text_char(s, str, len);
8323  return 1;
8324  }
8325  mem = nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0);
8326  if (!mem) return 0;
8327 
8328  /* memmove */
8329  NK_ASSERT(((int)pos + (int)len + ((int)copylen - 1)) >= 0);
8330  NK_ASSERT(((int)pos + ((int)copylen - 1)) >= 0);
8331  dst = nk_ptr_add(char, s->buffer.memory.ptr, pos + len + (copylen - 1));
8332  src = nk_ptr_add(char, s->buffer.memory.ptr, pos + (copylen-1));
8333  for (i = 0; i < copylen; ++i) *dst-- = *src--;
8334  mem = nk_ptr_add(void, s->buffer.memory.ptr, pos);
8335  NK_MEMCPY(mem, str, (nk_size)len * sizeof(char));
8336  s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
8337  return 1;
8338 }
8339 NK_API int
8340 nk_str_insert_at_rune(struct nk_str *str, int pos, const char *cstr, int len)
8341 {
8342  int glyph_len;
8343  nk_rune unicode;
8344  const char *begin;
8345  const char *buffer;
8346 
8347  NK_ASSERT(str);
8348  NK_ASSERT(cstr);
8349  NK_ASSERT(len);
8350  if (!str || !cstr || !len) return 0;
8351  begin = nk_str_at_rune(str, pos, &unicode, &glyph_len);
8352  if (!str->len)
8353  return nk_str_append_text_char(str, cstr, len);
8354  buffer = nk_str_get_const(str);
8355  if (!begin) return 0;
8356  return nk_str_insert_at_char(str, (int)(begin - buffer), cstr, len);
8357 }
8358 NK_API int
8359 nk_str_insert_text_char(struct nk_str *str, int pos, const char *text, int len)
8360 {
8361  return nk_str_insert_text_utf8(str, pos, text, len);
8362 }
8363 NK_API int
8364 nk_str_insert_str_char(struct nk_str *str, int pos, const char *text)
8365 {
8366  return nk_str_insert_text_utf8(str, pos, text, nk_strlen(text));
8367 }
8368 NK_API int
8369 nk_str_insert_text_utf8(struct nk_str *str, int pos, const char *text, int len)
8370 {
8371  int i = 0;
8372  int byte_len = 0;
8373  nk_rune unicode;
8374 
8375  NK_ASSERT(str);
8376  NK_ASSERT(text);
8377  if (!str || !text || !len) return 0;
8378  for (i = 0; i < len; ++i)
8379  byte_len += nk_utf_decode(text+byte_len, &unicode, 4);
8380  nk_str_insert_at_rune(str, pos, text, byte_len);
8381  return len;
8382 }
8383 NK_API int
8384 nk_str_insert_str_utf8(struct nk_str *str, int pos, const char *text)
8385 {
8386  int runes = 0;
8387  int byte_len = 0;
8388  int num_runes = 0;
8389  int glyph_len = 0;
8390  nk_rune unicode;
8391  if (!str || !text) return 0;
8392 
8393  glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4);
8394  while (unicode != '\0' && glyph_len) {
8395  glyph_len = nk_utf_decode(text+byte_len, &unicode, 4);
8396  byte_len += glyph_len;
8397  num_runes++;
8398  }
8399  nk_str_insert_at_rune(str, pos, text, byte_len);
8400  return runes;
8401 }
8402 NK_API int
8403 nk_str_insert_text_runes(struct nk_str *str, int pos, const nk_rune *runes, int len)
8404 {
8405  int i = 0;
8406  int byte_len = 0;
8407  nk_glyph glyph;
8408 
8409  NK_ASSERT(str);
8410  if (!str || !runes || !len) return 0;
8411  for (i = 0; i < len; ++i) {
8412  byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
8413  if (!byte_len) break;
8414  nk_str_insert_at_rune(str, pos+i, glyph, byte_len);
8415  }
8416  return len;
8417 }
8418 NK_API int
8419 nk_str_insert_str_runes(struct nk_str *str, int pos, const nk_rune *runes)
8420 {
8421  int i = 0;
8422  nk_glyph glyph;
8423  int byte_len;
8424  NK_ASSERT(str);
8425  if (!str || !runes) return 0;
8426  while (runes[i] != '\0') {
8427  byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
8428  nk_str_insert_at_rune(str, pos+i, glyph, byte_len);
8429  i++;
8430  }
8431  return i;
8432 }
8433 NK_API void
8434 nk_str_remove_chars(struct nk_str *s, int len)
8435 {
8436  NK_ASSERT(s);
8437  NK_ASSERT(len >= 0);
8438  if (!s || len < 0 || (nk_size)len > s->buffer.allocated) return;
8439  NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0);
8440  s->buffer.allocated -= (nk_size)len;
8441  s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
8442 }
8443 NK_API void
8444 nk_str_remove_runes(struct nk_str *str, int len)
8445 {
8446  int index;
8447  const char *begin;
8448  const char *end;
8449  nk_rune unicode;
8450 
8451  NK_ASSERT(str);
8452  NK_ASSERT(len >= 0);
8453  if (!str || len < 0) return;
8454  if (len >= str->len) {
8455  str->len = 0;
8456  return;
8457  }
8458 
8459  index = str->len - len;
8460  begin = nk_str_at_rune(str, index, &unicode, &len);
8461  end = (const char*)str->buffer.memory.ptr + str->buffer.allocated;
8462  nk_str_remove_chars(str, (int)(end-begin)+1);
8463 }
8464 NK_API void
8465 nk_str_delete_chars(struct nk_str *s, int pos, int len)
8466 {
8467  NK_ASSERT(s);
8468  if (!s || !len || (nk_size)pos > s->buffer.allocated ||
8469  (nk_size)(pos + len) > s->buffer.allocated) return;
8470 
8471  if ((nk_size)(pos + len) < s->buffer.allocated) {
8472  /* memmove */
8473  char *dst = nk_ptr_add(char, s->buffer.memory.ptr, pos);
8474  char *src = nk_ptr_add(char, s->buffer.memory.ptr, pos + len);
8475  NK_MEMCPY(dst, src, s->buffer.allocated - (nk_size)(pos + len));
8476  NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0);
8477  s->buffer.allocated -= (nk_size)len;
8478  } else nk_str_remove_chars(s, len);
8479  s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
8480 }
8481 NK_API void
8482 nk_str_delete_runes(struct nk_str *s, int pos, int len)
8483 {
8484  char *temp;
8485  nk_rune unicode;
8486  char *begin;
8487  char *end;
8488  int unused;
8489 
8490  NK_ASSERT(s);
8491  NK_ASSERT(s->len >= pos + len);
8492  if (s->len < pos + len)
8493  len = NK_CLAMP(0, (s->len - pos), s->len);
8494  if (!len) return;
8495 
8496  temp = (char *)s->buffer.memory.ptr;
8497  begin = nk_str_at_rune(s, pos, &unicode, &unused);
8498  if (!begin) return;
8499  s->buffer.memory.ptr = begin;
8500  end = nk_str_at_rune(s, len, &unicode, &unused);
8501  s->buffer.memory.ptr = temp;
8502  if (!end) return;
8503  nk_str_delete_chars(s, (int)(begin - temp), (int)(end - begin));
8504 }
8505 NK_API char*
8506 nk_str_at_char(struct nk_str *s, int pos)
8507 {
8508  NK_ASSERT(s);
8509  if (!s || pos > (int)s->buffer.allocated) return 0;
8510  return nk_ptr_add(char, s->buffer.memory.ptr, pos);
8511 }
8512 NK_API char*
8513 nk_str_at_rune(struct nk_str *str, int pos, nk_rune *unicode, int *len)
8514 {
8515  int i = 0;
8516  int src_len = 0;
8517  int glyph_len = 0;
8518  char *text;
8519  int text_len;
8520 
8521  NK_ASSERT(str);
8522  NK_ASSERT(unicode);
8523  NK_ASSERT(len);
8524 
8525  if (!str || !unicode || !len) return 0;
8526  if (pos < 0) {
8527  *unicode = 0;
8528  *len = 0;
8529  return 0;
8530  }
8531 
8532  text = (char*)str->buffer.memory.ptr;
8533  text_len = (int)str->buffer.allocated;
8534  glyph_len = nk_utf_decode(text, unicode, text_len);
8535  while (glyph_len) {
8536  if (i == pos) {
8537  *len = glyph_len;
8538  break;
8539  }
8540 
8541  i++;
8542  src_len = src_len + glyph_len;
8543  glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
8544  }
8545  if (i != pos) return 0;
8546  return text + src_len;
8547 }
8548 NK_API const char*
8549 nk_str_at_char_const(const struct nk_str *s, int pos)
8550 {
8551  NK_ASSERT(s);
8552  if (!s || pos > (int)s->buffer.allocated) return 0;
8553  return nk_ptr_add(char, s->buffer.memory.ptr, pos);
8554 }
8555 NK_API const char*
8556 nk_str_at_const(const struct nk_str *str, int pos, nk_rune *unicode, int *len)
8557 {
8558  int i = 0;
8559  int src_len = 0;
8560  int glyph_len = 0;
8561  char *text;
8562  int text_len;
8563 
8564  NK_ASSERT(str);
8565  NK_ASSERT(unicode);
8566  NK_ASSERT(len);
8567 
8568  if (!str || !unicode || !len) return 0;
8569  if (pos < 0) {
8570  *unicode = 0;
8571  *len = 0;
8572  return 0;
8573  }
8574 
8575  text = (char*)str->buffer.memory.ptr;
8576  text_len = (int)str->buffer.allocated;
8577  glyph_len = nk_utf_decode(text, unicode, text_len);
8578  while (glyph_len) {
8579  if (i == pos) {
8580  *len = glyph_len;
8581  break;
8582  }
8583 
8584  i++;
8585  src_len = src_len + glyph_len;
8586  glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
8587  }
8588  if (i != pos) return 0;
8589  return text + src_len;
8590 }
8592 nk_str_rune_at(const struct nk_str *str, int pos)
8593 {
8594  int len;
8595  nk_rune unicode = 0;
8596  nk_str_at_const(str, pos, &unicode, &len);
8597  return unicode;
8598 }
8599 NK_API char*
8600 nk_str_get(struct nk_str *s)
8601 {
8602  NK_ASSERT(s);
8603  if (!s || !s->len || !s->buffer.allocated) return 0;
8604  return (char*)s->buffer.memory.ptr;
8605 }
8606 NK_API const char*
8607 nk_str_get_const(const struct nk_str *s)
8608 {
8609  NK_ASSERT(s);
8610  if (!s || !s->len || !s->buffer.allocated) return 0;
8611  return (const char*)s->buffer.memory.ptr;
8612 }
8613 NK_API int
8614 nk_str_len(struct nk_str *s)
8615 {
8616  NK_ASSERT(s);
8617  if (!s || !s->len || !s->buffer.allocated) return 0;
8618  return s->len;
8619 }
8620 NK_API int
8621 nk_str_len_char(struct nk_str *s)
8622 {
8623  NK_ASSERT(s);
8624  if (!s || !s->len || !s->buffer.allocated) return 0;
8625  return (int)s->buffer.allocated;
8626 }
8627 NK_API void
8628 nk_str_clear(struct nk_str *str)
8629 {
8630  NK_ASSERT(str);
8631  nk_buffer_clear(&str->buffer);
8632  str->len = 0;
8633 }
8634 NK_API void
8635 nk_str_free(struct nk_str *str)
8636 {
8637  NK_ASSERT(str);
8638  nk_buffer_free(&str->buffer);
8639  str->len = 0;
8640 }
8641 
8642 
8643 
8644 
8645 
8646 /* ==============================================================
8647  *
8648  * DRAW
8649  *
8650  * ===============================================================*/
8651 NK_LIB void
8652 nk_command_buffer_init(struct nk_command_buffer *cb,
8653  struct nk_buffer *b, enum nk_command_clipping clip)
8654 {
8655  NK_ASSERT(cb);
8656  NK_ASSERT(b);
8657  if (!cb || !b) return;
8658  cb->base = b;
8659  cb->use_clipping = (int)clip;
8660  cb->begin = b->allocated;
8661  cb->end = b->allocated;
8662  cb->last = b->allocated;
8663 }
8664 NK_LIB void
8665 nk_command_buffer_reset(struct nk_command_buffer *b)
8666 {
8667  NK_ASSERT(b);
8668  if (!b) return;
8669  b->begin = 0;
8670  b->end = 0;
8671  b->last = 0;
8672  b->clip = nk_null_rect;
8673 #ifdef NK_INCLUDE_COMMAND_USERDATA
8674  b->userdata.ptr = 0;
8675 #endif
8676 }
8677 NK_LIB void*
8678 nk_command_buffer_push(struct nk_command_buffer* b,
8679  enum nk_command_type t, nk_size size)
8680 {
8681  NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_command);
8682  struct nk_command *cmd;
8683  nk_size alignment;
8684  void *unaligned;
8685  void *memory;
8686 
8687  NK_ASSERT(b);
8688  NK_ASSERT(b->base);
8689  if (!b) return 0;
8690  cmd = (struct nk_command*)nk_buffer_alloc(b->base,NK_BUFFER_FRONT,size,align);
8691  if (!cmd) return 0;
8692 
8693  /* make sure the offset to the next command is aligned */
8694  b->last = (nk_size)((nk_byte*)cmd - (nk_byte*)b->base->memory.ptr);
8695  unaligned = (nk_byte*)cmd + size;
8696  memory = NK_ALIGN_PTR(unaligned, align);
8697  alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned);
8698 #ifdef NK_ZERO_COMMAND_MEMORY
8699  NK_MEMSET(cmd, 0, size + alignment);
8700 #endif
8701 
8702  cmd->type = t;
8703  cmd->next = b->base->allocated + alignment;
8704 #ifdef NK_INCLUDE_COMMAND_USERDATA
8705  cmd->userdata = b->userdata;
8706 #endif
8707  b->end = cmd->next;
8708  return cmd;
8709 }
8710 NK_API void
8711 nk_push_scissor(struct nk_command_buffer *b, struct nk_rect r)
8712 {
8713  struct nk_command_scissor *cmd;
8714  NK_ASSERT(b);
8715  if (!b) return;
8716 
8717  b->clip.x = r.x;
8718  b->clip.y = r.y;
8719  b->clip.w = r.w;
8720  b->clip.h = r.h;
8721  cmd = (struct nk_command_scissor*)
8722  nk_command_buffer_push(b, NK_COMMAND_SCISSOR, sizeof(*cmd));
8723 
8724  if (!cmd) return;
8725  cmd->x = (short)r.x;
8726  cmd->y = (short)r.y;
8727  cmd->w = (unsigned short)NK_MAX(0, r.w);
8728  cmd->h = (unsigned short)NK_MAX(0, r.h);
8729 }
8730 NK_API void
8731 nk_stroke_line(struct nk_command_buffer *b, float x0, float y0,
8732  float x1, float y1, float line_thickness, struct nk_color c)
8733 {
8734  struct nk_command_line *cmd;
8735  NK_ASSERT(b);
8736  if (!b || line_thickness <= 0) return;
8737  cmd = (struct nk_command_line*)
8738  nk_command_buffer_push(b, NK_COMMAND_LINE, sizeof(*cmd));
8739  if (!cmd) return;
8740  cmd->line_thickness = (unsigned short)line_thickness;
8741  cmd->begin.x = (short)x0;
8742  cmd->begin.y = (short)y0;
8743  cmd->end.x = (short)x1;
8744  cmd->end.y = (short)y1;
8745  cmd->color = c;
8746 }
8747 NK_API void
8748 nk_stroke_curve(struct nk_command_buffer *b, float ax, float ay,
8749  float ctrl0x, float ctrl0y, float ctrl1x, float ctrl1y,
8750  float bx, float by, float line_thickness, struct nk_color col)
8751 {
8752  struct nk_command_curve *cmd;
8753  NK_ASSERT(b);
8754  if (!b || col.a == 0 || line_thickness <= 0) return;
8755 
8756  cmd = (struct nk_command_curve*)
8757  nk_command_buffer_push(b, NK_COMMAND_CURVE, sizeof(*cmd));
8758  if (!cmd) return;
8759  cmd->line_thickness = (unsigned short)line_thickness;
8760  cmd->begin.x = (short)ax;
8761  cmd->begin.y = (short)ay;
8762  cmd->ctrl[0].x = (short)ctrl0x;
8763  cmd->ctrl[0].y = (short)ctrl0y;
8764  cmd->ctrl[1].x = (short)ctrl1x;
8765  cmd->ctrl[1].y = (short)ctrl1y;
8766  cmd->end.x = (short)bx;
8767  cmd->end.y = (short)by;
8768  cmd->color = col;
8769 }
8770 NK_API void
8771 nk_stroke_rect(struct nk_command_buffer *b, struct nk_rect rect,
8772  float rounding, float line_thickness, struct nk_color c)
8773 {
8774  struct nk_command_rect *cmd;
8775  NK_ASSERT(b);
8776  if (!b || c.a == 0 || rect.w == 0 || rect.h == 0 || line_thickness <= 0) return;
8777  if (b->use_clipping) {
8778  const struct nk_rect *clip = &b->clip;
8779  if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
8780  clip->x, clip->y, clip->w, clip->h)) return;
8781  }
8782  cmd = (struct nk_command_rect*)
8783  nk_command_buffer_push(b, NK_COMMAND_RECT, sizeof(*cmd));
8784  if (!cmd) return;
8785  cmd->rounding = (unsigned short)rounding;
8786  cmd->line_thickness = (unsigned short)line_thickness;
8787  cmd->x = (short)rect.x;
8788  cmd->y = (short)rect.y;
8789  cmd->w = (unsigned short)NK_MAX(0, rect.w);
8790  cmd->h = (unsigned short)NK_MAX(0, rect.h);
8791  cmd->color = c;
8792 }
8793 NK_API void
8794 nk_fill_rect(struct nk_command_buffer *b, struct nk_rect rect,
8795  float rounding, struct nk_color c)
8796 {
8797  struct nk_command_rect_filled *cmd;
8798  NK_ASSERT(b);
8799  if (!b || c.a == 0 || rect.w == 0 || rect.h == 0) return;
8800  if (b->use_clipping) {
8801  const struct nk_rect *clip = &b->clip;
8802  if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
8803  clip->x, clip->y, clip->w, clip->h)) return;
8804  }
8805 
8806  cmd = (struct nk_command_rect_filled*)
8807  nk_command_buffer_push(b, NK_COMMAND_RECT_FILLED, sizeof(*cmd));
8808  if (!cmd) return;
8809  cmd->rounding = (unsigned short)rounding;
8810  cmd->x = (short)rect.x;
8811  cmd->y = (short)rect.y;
8812  cmd->w = (unsigned short)NK_MAX(0, rect.w);
8813  cmd->h = (unsigned short)NK_MAX(0, rect.h);
8814  cmd->color = c;
8815 }
8816 NK_API void
8817 nk_fill_rect_multi_color(struct nk_command_buffer *b, struct nk_rect rect,
8818  struct nk_color left, struct nk_color top, struct nk_color right,
8819  struct nk_color bottom)
8820 {
8821  struct nk_command_rect_multi_color *cmd;
8822  NK_ASSERT(b);
8823  if (!b || rect.w == 0 || rect.h == 0) return;
8824  if (b->use_clipping) {
8825  const struct nk_rect *clip = &b->clip;
8826  if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
8827  clip->x, clip->y, clip->w, clip->h)) return;
8828  }
8829 
8830  cmd = (struct nk_command_rect_multi_color*)
8831  nk_command_buffer_push(b, NK_COMMAND_RECT_MULTI_COLOR, sizeof(*cmd));
8832  if (!cmd) return;
8833  cmd->x = (short)rect.x;
8834  cmd->y = (short)rect.y;
8835  cmd->w = (unsigned short)NK_MAX(0, rect.w);
8836  cmd->h = (unsigned short)NK_MAX(0, rect.h);
8837  cmd->left = left;
8838  cmd->top = top;
8839  cmd->right = right;
8840  cmd->bottom = bottom;
8841 }
8842 NK_API void
8843 nk_stroke_circle(struct nk_command_buffer *b, struct nk_rect r,
8844  float line_thickness, struct nk_color c)
8845 {
8846  struct nk_command_circle *cmd;
8847  if (!b || r.w == 0 || r.h == 0 || line_thickness <= 0) return;
8848  if (b->use_clipping) {
8849  const struct nk_rect *clip = &b->clip;
8850  if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h))
8851  return;
8852  }
8853 
8854  cmd = (struct nk_command_circle*)
8855  nk_command_buffer_push(b, NK_COMMAND_CIRCLE, sizeof(*cmd));
8856  if (!cmd) return;
8857  cmd->line_thickness = (unsigned short)line_thickness;
8858  cmd->x = (short)r.x;
8859  cmd->y = (short)r.y;
8860  cmd->w = (unsigned short)NK_MAX(r.w, 0);
8861  cmd->h = (unsigned short)NK_MAX(r.h, 0);
8862  cmd->color = c;
8863 }
8864 NK_API void
8865 nk_fill_circle(struct nk_command_buffer *b, struct nk_rect r, struct nk_color c)
8866 {
8867  struct nk_command_circle_filled *cmd;
8868  NK_ASSERT(b);
8869  if (!b || c.a == 0 || r.w == 0 || r.h == 0) return;
8870  if (b->use_clipping) {
8871  const struct nk_rect *clip = &b->clip;
8872  if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h))
8873  return;
8874  }
8875 
8876  cmd = (struct nk_command_circle_filled*)
8877  nk_command_buffer_push(b, NK_COMMAND_CIRCLE_FILLED, sizeof(*cmd));
8878  if (!cmd) return;
8879  cmd->x = (short)r.x;
8880  cmd->y = (short)r.y;
8881  cmd->w = (unsigned short)NK_MAX(r.w, 0);
8882  cmd->h = (unsigned short)NK_MAX(r.h, 0);
8883  cmd->color = c;
8884 }
8885 NK_API void
8886 nk_stroke_arc(struct nk_command_buffer *b, float cx, float cy, float radius,
8887  float a_min, float a_max, float line_thickness, struct nk_color c)
8888 {
8889  struct nk_command_arc *cmd;
8890  if (!b || c.a == 0 || line_thickness <= 0) return;
8891  cmd = (struct nk_command_arc*)
8892  nk_command_buffer_push(b, NK_COMMAND_ARC, sizeof(*cmd));
8893  if (!cmd) return;
8894  cmd->line_thickness = (unsigned short)line_thickness;
8895  cmd->cx = (short)cx;
8896  cmd->cy = (short)cy;
8897  cmd->r = (unsigned short)radius;
8898  cmd->a[0] = a_min;
8899  cmd->a[1] = a_max;
8900  cmd->color = c;
8901 }
8902 NK_API void
8903 nk_fill_arc(struct nk_command_buffer *b, float cx, float cy, float radius,
8904  float a_min, float a_max, struct nk_color c)
8905 {
8906  struct nk_command_arc_filled *cmd;
8907  NK_ASSERT(b);
8908  if (!b || c.a == 0) return;
8909  cmd = (struct nk_command_arc_filled*)
8910  nk_command_buffer_push(b, NK_COMMAND_ARC_FILLED, sizeof(*cmd));
8911  if (!cmd) return;
8912  cmd->cx = (short)cx;
8913  cmd->cy = (short)cy;
8914  cmd->r = (unsigned short)radius;
8915  cmd->a[0] = a_min;
8916  cmd->a[1] = a_max;
8917  cmd->color = c;
8918 }
8919 NK_API void
8920 nk_stroke_triangle(struct nk_command_buffer *b, float x0, float y0, float x1,
8921  float y1, float x2, float y2, float line_thickness, struct nk_color c)
8922 {
8923  struct nk_command_triangle *cmd;
8924  NK_ASSERT(b);
8925  if (!b || c.a == 0 || line_thickness <= 0) return;
8926  if (b->use_clipping) {
8927  const struct nk_rect *clip = &b->clip;
8928  if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) &&
8929  !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) &&
8930  !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h))
8931  return;
8932  }
8933 
8934  cmd = (struct nk_command_triangle*)
8935  nk_command_buffer_push(b, NK_COMMAND_TRIANGLE, sizeof(*cmd));
8936  if (!cmd) return;
8937  cmd->line_thickness = (unsigned short)line_thickness;
8938  cmd->a.x = (short)x0;
8939  cmd->a.y = (short)y0;
8940  cmd->b.x = (short)x1;
8941  cmd->b.y = (short)y1;
8942  cmd->c.x = (short)x2;
8943  cmd->c.y = (short)y2;
8944  cmd->color = c;
8945 }
8946 NK_API void
8947 nk_fill_triangle(struct nk_command_buffer *b, float x0, float y0, float x1,
8948  float y1, float x2, float y2, struct nk_color c)
8949 {
8950  struct nk_command_triangle_filled *cmd;
8951  NK_ASSERT(b);
8952  if (!b || c.a == 0) return;
8953  if (!b) return;
8954  if (b->use_clipping) {
8955  const struct nk_rect *clip = &b->clip;
8956  if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) &&
8957  !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) &&
8958  !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h))
8959  return;
8960  }
8961 
8962  cmd = (struct nk_command_triangle_filled*)
8963  nk_command_buffer_push(b, NK_COMMAND_TRIANGLE_FILLED, sizeof(*cmd));
8964  if (!cmd) return;
8965  cmd->a.x = (short)x0;
8966  cmd->a.y = (short)y0;
8967  cmd->b.x = (short)x1;
8968  cmd->b.y = (short)y1;
8969  cmd->c.x = (short)x2;
8970  cmd->c.y = (short)y2;
8971  cmd->color = c;
8972 }
8973 NK_API void
8974 nk_stroke_polygon(struct nk_command_buffer *b, float *points, int point_count,
8975  float line_thickness, struct nk_color col)
8976 {
8977  int i;
8978  nk_size size = 0;
8979  struct nk_command_polygon *cmd;
8980 
8981  NK_ASSERT(b);
8982  if (!b || col.a == 0 || line_thickness <= 0) return;
8983  size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
8984  cmd = (struct nk_command_polygon*) nk_command_buffer_push(b, NK_COMMAND_POLYGON, size);
8985  if (!cmd) return;
8986  cmd->color = col;
8987  cmd->line_thickness = (unsigned short)line_thickness;
8988  cmd->point_count = (unsigned short)point_count;
8989  for (i = 0; i < point_count; ++i) {
8990  cmd->points[i].x = (short)points[i*2];
8991  cmd->points[i].y = (short)points[i*2+1];
8992  }
8993 }
8994 NK_API void
8995 nk_fill_polygon(struct nk_command_buffer *b, float *points, int point_count,
8996  struct nk_color col)
8997 {
8998  int i;
8999  nk_size size = 0;
9000  struct nk_command_polygon_filled *cmd;
9001 
9002  NK_ASSERT(b);
9003  if (!b || col.a == 0) return;
9004  size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
9005  cmd = (struct nk_command_polygon_filled*)
9006  nk_command_buffer_push(b, NK_COMMAND_POLYGON_FILLED, size);
9007  if (!cmd) return;
9008  cmd->color = col;
9009  cmd->point_count = (unsigned short)point_count;
9010  for (i = 0; i < point_count; ++i) {
9011  cmd->points[i].x = (short)points[i*2+0];
9012  cmd->points[i].y = (short)points[i*2+1];
9013  }
9014 }
9015 NK_API void
9017  float line_thickness, struct nk_color col)
9018 {
9019  int i;
9020  nk_size size = 0;
9021  struct nk_command_polyline *cmd;
9022 
9023  NK_ASSERT(b);
9024  if (!b || col.a == 0 || line_thickness <= 0) return;
9025  size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
9026  cmd = (struct nk_command_polyline*) nk_command_buffer_push(b, NK_COMMAND_POLYLINE, size);
9027  if (!cmd) return;
9028  cmd->color = col;
9029  cmd->point_count = (unsigned short)point_count;
9030  cmd->line_thickness = (unsigned short)line_thickness;
9031  for (i = 0; i < point_count; ++i) {
9032  cmd->points[i].x = (short)points[i*2];
9033  cmd->points[i].y = (short)points[i*2+1];
9034  }
9035 }
9036 NK_API void
9037 nk_draw_image(struct nk_command_buffer *b, struct nk_rect r,
9038  const struct nk_image *img, struct nk_color col)
9039 {
9040  struct nk_command_image *cmd;
9041  NK_ASSERT(b);
9042  if (!b) return;
9043  if (b->use_clipping) {
9044  const struct nk_rect *c = &b->clip;
9045  if (c->w == 0 || c->h == 0 || !NK_INTERSECT(r.x, r.y, r.w, r.h, c->x, c->y, c->w, c->h))
9046  return;
9047  }
9048 
9049  cmd = (struct nk_command_image*)
9050  nk_command_buffer_push(b, NK_COMMAND_IMAGE, sizeof(*cmd));
9051  if (!cmd) return;
9052  cmd->x = (short)r.x;
9053  cmd->y = (short)r.y;
9054  cmd->w = (unsigned short)NK_MAX(0, r.w);
9055  cmd->h = (unsigned short)NK_MAX(0, r.h);
9056  cmd->img = *img;
9057  cmd->col = col;
9058 }
9059 NK_API void
9060 nk_push_custom(struct nk_command_buffer *b, struct nk_rect r,
9062 {
9063  struct nk_command_custom *cmd;
9064  NK_ASSERT(b);
9065  if (!b) return;
9066  if (b->use_clipping) {
9067  const struct nk_rect *c = &b->clip;
9068  if (c->w == 0 || c->h == 0 || !NK_INTERSECT(r.x, r.y, r.w, r.h, c->x, c->y, c->w, c->h))
9069  return;
9070  }
9071 
9072  cmd = (struct nk_command_custom*)
9073  nk_command_buffer_push(b, NK_COMMAND_CUSTOM, sizeof(*cmd));
9074  if (!cmd) return;
9075  cmd->x = (short)r.x;
9076  cmd->y = (short)r.y;
9077  cmd->w = (unsigned short)NK_MAX(0, r.w);
9078  cmd->h = (unsigned short)NK_MAX(0, r.h);
9079  cmd->callback_data = usr;
9080  cmd->callback = cb;
9081 }
9082 NK_API void
9083 nk_draw_text(struct nk_command_buffer *b, struct nk_rect r,
9084  const char *string, int length, const struct nk_user_font *font,
9085  struct nk_color bg, struct nk_color fg)
9086 {
9087  float text_width = 0;
9088  struct nk_command_text *cmd;
9089 
9090  NK_ASSERT(b);
9091  NK_ASSERT(font);
9092  if (!b || !string || !length || (bg.a == 0 && fg.a == 0)) return;
9093  if (b->use_clipping) {
9094  const struct nk_rect *c = &b->clip;
9095  if (c->w == 0 || c->h == 0 || !NK_INTERSECT(r.x, r.y, r.w, r.h, c->x, c->y, c->w, c->h))
9096  return;
9097  }
9098 
9099  /* make sure text fits inside bounds */
9100  text_width = font->width(font->userdata, font->height, string, length);
9101  if (text_width > r.w){
9102  int glyphs = 0;
9103  float txt_width = (float)text_width;
9104  length = nk_text_clamp(font, string, length, r.w, &glyphs, &txt_width, 0,0);
9105  }
9106 
9107  if (!length) return;
9108  cmd = (struct nk_command_text*)
9109  nk_command_buffer_push(b, NK_COMMAND_TEXT, sizeof(*cmd) + (nk_size)(length + 1));
9110  if (!cmd) return;
9111  cmd->x = (short)r.x;
9112  cmd->y = (short)r.y;
9113  cmd->w = (unsigned short)r.w;
9114  cmd->h = (unsigned short)r.h;
9115  cmd->background = bg;
9116  cmd->foreground = fg;
9117  cmd->font = font;
9118  cmd->length = length;
9119  cmd->height = font->height;
9120  NK_MEMCPY(cmd->string, string, (nk_size)length);
9121  cmd->string[length] = '\0';
9122 }
9123 
9124 
9125 
9126 
9127 
9128 /* ===============================================================
9129  *
9130  * VERTEX
9131  *
9132  * ===============================================================*/
9133 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
9134 NK_API void
9135 nk_draw_list_init(struct nk_draw_list *list)
9136 {
9137  nk_size i = 0;
9138  NK_ASSERT(list);
9139  if (!list) return;
9140  nk_zero(list, sizeof(*list));
9141  for (i = 0; i < NK_LEN(list->circle_vtx); ++i) {
9142  const float a = ((float)i / (float)NK_LEN(list->circle_vtx)) * 2 * NK_PI;
9143  list->circle_vtx[i].x = (float)NK_COS(a);
9144  list->circle_vtx[i].y = (float)NK_SIN(a);
9145  }
9146 }
9147 NK_API void
9148 nk_draw_list_setup(struct nk_draw_list *canvas, const struct nk_convert_config *config,
9149  struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements,
9150  enum nk_anti_aliasing line_aa, enum nk_anti_aliasing shape_aa)
9151 {
9152  NK_ASSERT(canvas);
9153  NK_ASSERT(config);
9154  NK_ASSERT(cmds);
9155  NK_ASSERT(vertices);
9156  NK_ASSERT(elements);
9157  if (!canvas || !config || !cmds || !vertices || !elements)
9158  return;
9159 
9160  canvas->buffer = cmds;
9161  canvas->config = *config;
9162  canvas->elements = elements;
9163  canvas->vertices = vertices;
9164  canvas->line_AA = line_aa;
9165  canvas->shape_AA = shape_aa;
9166  canvas->clip_rect = nk_null_rect;
9167 
9168  canvas->cmd_offset = 0;
9169  canvas->element_count = 0;
9170  canvas->vertex_count = 0;
9171  canvas->cmd_offset = 0;
9172  canvas->cmd_count = 0;
9173  canvas->path_count = 0;
9174 }
9175 NK_API const struct nk_draw_command*
9176 nk__draw_list_begin(const struct nk_draw_list *canvas, const struct nk_buffer *buffer)
9177 {
9178  nk_byte *memory;
9179  nk_size offset;
9180  const struct nk_draw_command *cmd;
9181 
9182  NK_ASSERT(buffer);
9183  if (!buffer || !buffer->size || !canvas->cmd_count)
9184  return 0;
9185 
9186  memory = (nk_byte*)buffer->memory.ptr;
9187  offset = buffer->memory.size - canvas->cmd_offset;
9188  cmd = nk_ptr_add(const struct nk_draw_command, memory, offset);
9189  return cmd;
9190 }
9191 NK_API const struct nk_draw_command*
9192 nk__draw_list_end(const struct nk_draw_list *canvas, const struct nk_buffer *buffer)
9193 {
9194  nk_size size;
9195  nk_size offset;
9196  nk_byte *memory;
9197  const struct nk_draw_command *end;
9198 
9199  NK_ASSERT(buffer);
9200  NK_ASSERT(canvas);
9201  if (!buffer || !canvas)
9202  return 0;
9203 
9204  memory = (nk_byte*)buffer->memory.ptr;
9205  size = buffer->memory.size;
9206  offset = size - canvas->cmd_offset;
9207  end = nk_ptr_add(const struct nk_draw_command, memory, offset);
9208  end -= (canvas->cmd_count-1);
9209  return end;
9210 }
9211 NK_API const struct nk_draw_command*
9212 nk__draw_list_next(const struct nk_draw_command *cmd,
9213  const struct nk_buffer *buffer, const struct nk_draw_list *canvas)
9214 {
9215  const struct nk_draw_command *end;
9216  NK_ASSERT(buffer);
9217  NK_ASSERT(canvas);
9218  if (!cmd || !buffer || !canvas)
9219  return 0;
9220 
9221  end = nk__draw_list_end(canvas, buffer);
9222  if (cmd <= end) return 0;
9223  return (cmd-1);
9224 }
9225 NK_INTERN struct nk_vec2*
9226 nk_draw_list_alloc_path(struct nk_draw_list *list, int count)
9227 {
9228  struct nk_vec2 *points;
9229  NK_STORAGE const nk_size point_align = NK_ALIGNOF(struct nk_vec2);
9230  NK_STORAGE const nk_size point_size = sizeof(struct nk_vec2);
9231  points = (struct nk_vec2*)
9232  nk_buffer_alloc(list->buffer, NK_BUFFER_FRONT,
9233  point_size * (nk_size)count, point_align);
9234 
9235  if (!points) return 0;
9236  if (!list->path_offset) {
9237  void *memory = nk_buffer_memory(list->buffer);
9238  list->path_offset = (unsigned int)((nk_byte*)points - (nk_byte*)memory);
9239  }
9240  list->path_count += (unsigned int)count;
9241  return points;
9242 }
9243 NK_INTERN struct nk_vec2
9244 nk_draw_list_path_last(struct nk_draw_list *list)
9245 {
9246  void *memory;
9247  struct nk_vec2 *point;
9248  NK_ASSERT(list->path_count);
9249  memory = nk_buffer_memory(list->buffer);
9250  point = nk_ptr_add(struct nk_vec2, memory, list->path_offset);
9251  point += (list->path_count-1);
9252  return *point;
9253 }
9254 NK_INTERN struct nk_draw_command*
9255 nk_draw_list_push_command(struct nk_draw_list *list, struct nk_rect clip,
9256  nk_handle texture)
9257 {
9258  NK_STORAGE const nk_size cmd_align = NK_ALIGNOF(struct nk_draw_command);
9259  NK_STORAGE const nk_size cmd_size = sizeof(struct nk_draw_command);
9260  struct nk_draw_command *cmd;
9261 
9262  NK_ASSERT(list);
9263  cmd = (struct nk_draw_command*)
9264  nk_buffer_alloc(list->buffer, NK_BUFFER_BACK, cmd_size, cmd_align);
9265 
9266  if (!cmd) return 0;
9267  if (!list->cmd_count) {
9268  nk_byte *memory = (nk_byte*)nk_buffer_memory(list->buffer);
9269  nk_size total = nk_buffer_total(list->buffer);
9270  memory = nk_ptr_add(nk_byte, memory, total);
9271  list->cmd_offset = (nk_size)(memory - (nk_byte*)cmd);
9272  }
9273 
9274  cmd->elem_count = 0;
9275  cmd->clip_rect = clip;
9276  cmd->texture = texture;
9277 #ifdef NK_INCLUDE_COMMAND_USERDATA
9278  cmd->userdata = list->userdata;
9279 #endif
9280 
9281  list->cmd_count++;
9282  list->clip_rect = clip;
9283  return cmd;
9284 }
9285 NK_INTERN struct nk_draw_command*
9286 nk_draw_list_command_last(struct nk_draw_list *list)
9287 {
9288  void *memory;
9289  nk_size size;
9290  struct nk_draw_command *cmd;
9291  NK_ASSERT(list->cmd_count);
9292 
9293  memory = nk_buffer_memory(list->buffer);
9294  size = nk_buffer_total(list->buffer);
9295  cmd = nk_ptr_add(struct nk_draw_command, memory, size - list->cmd_offset);
9296  return (cmd - (list->cmd_count-1));
9297 }
9298 NK_INTERN void
9299 nk_draw_list_add_clip(struct nk_draw_list *list, struct nk_rect rect)
9300 {
9301  NK_ASSERT(list);
9302  if (!list) return;
9303  if (!list->cmd_count) {
9304  nk_draw_list_push_command(list, rect, list->config.null.texture);
9305  } else {
9306  struct nk_draw_command *prev = nk_draw_list_command_last(list);
9307  if (prev->elem_count == 0)
9308  prev->clip_rect = rect;
9309  nk_draw_list_push_command(list, rect, prev->texture);
9310  }
9311 }
9312 NK_INTERN void
9313 nk_draw_list_push_image(struct nk_draw_list *list, nk_handle texture)
9314 {
9315  NK_ASSERT(list);
9316  if (!list) return;
9317  if (!list->cmd_count) {
9318  nk_draw_list_push_command(list, nk_null_rect, texture);
9319  } else {
9320  struct nk_draw_command *prev = nk_draw_list_command_last(list);
9321  if (prev->elem_count == 0) {
9322  prev->texture = texture;
9323  #ifdef NK_INCLUDE_COMMAND_USERDATA
9324  prev->userdata = list->userdata;
9325  #endif
9326  } else if (prev->texture.id != texture.id
9327  #ifdef NK_INCLUDE_COMMAND_USERDATA
9328  || prev->userdata.id != list->userdata.id
9329  #endif
9330  ) nk_draw_list_push_command(list, prev->clip_rect, texture);
9331  }
9332 }
9333 #ifdef NK_INCLUDE_COMMAND_USERDATA
9334 NK_API void
9335 nk_draw_list_push_userdata(struct nk_draw_list *list, nk_handle userdata)
9336 {
9337  list->userdata = userdata;
9338 }
9339 #endif
9340 NK_INTERN void*
9341 nk_draw_list_alloc_vertices(struct nk_draw_list *list, nk_size count)
9342 {
9343  void *vtx;
9344  NK_ASSERT(list);
9345  if (!list) return 0;
9346  vtx = nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT,
9347  list->config.vertex_size*count, list->config.vertex_alignment);
9348  if (!vtx) return 0;
9349  list->vertex_count += (unsigned int)count;
9350  return vtx;
9351 }
9352 NK_INTERN nk_draw_index*
9353 nk_draw_list_alloc_elements(struct nk_draw_list *list, nk_size count)
9354 {
9355  nk_draw_index *ids;
9356  struct nk_draw_command *cmd;
9357  NK_STORAGE const nk_size elem_align = NK_ALIGNOF(nk_draw_index);
9358  NK_STORAGE const nk_size elem_size = sizeof(nk_draw_index);
9359  NK_ASSERT(list);
9360  if (!list) return 0;
9361 
9362  ids = (nk_draw_index*)
9363  nk_buffer_alloc(list->elements, NK_BUFFER_FRONT, elem_size*count, elem_align);
9364  if (!ids) return 0;
9365  cmd = nk_draw_list_command_last(list);
9366  list->element_count += (unsigned int)count;
9367  cmd->elem_count += (unsigned int)count;
9368  return ids;
9369 }
9370 NK_INTERN int
9371 nk_draw_vertex_layout_element_is_end_of_layout(
9372  const struct nk_draw_vertex_layout_element *element)
9373 {
9374  return (element->attribute == NK_VERTEX_ATTRIBUTE_COUNT ||
9375  element->format == NK_FORMAT_COUNT);
9376 }
9377 NK_INTERN void
9378 nk_draw_vertex_color(void *attr, const float *vals,
9379  enum nk_draw_vertex_layout_format format)
9380 {
9381  /* if this triggers you tried to provide a value format for a color */
9382  float val[4];
9383  NK_ASSERT(format >= NK_FORMAT_COLOR_BEGIN);
9384  NK_ASSERT(format <= NK_FORMAT_COLOR_END);
9385  if (format < NK_FORMAT_COLOR_BEGIN || format > NK_FORMAT_COLOR_END) return;
9386 
9387  val[0] = NK_SATURATE(vals[0]);
9388  val[1] = NK_SATURATE(vals[1]);
9389  val[2] = NK_SATURATE(vals[2]);
9390  val[3] = NK_SATURATE(vals[3]);
9391 
9392  switch (format) {
9393  default: NK_ASSERT(0 && "Invalid vertex layout color format"); break;
9394  case NK_FORMAT_R8G8B8A8:
9395  case NK_FORMAT_R8G8B8: {
9396  struct nk_color col = nk_rgba_fv(val);
9397  NK_MEMCPY(attr, &col.r, sizeof(col));
9398  } break;
9399  case NK_FORMAT_B8G8R8A8: {
9400  struct nk_color col = nk_rgba_fv(val);
9401  struct nk_color bgra = nk_rgba(col.b, col.g, col.r, col.a);
9402  NK_MEMCPY(attr, &bgra, sizeof(bgra));
9403  } break;
9404  case NK_FORMAT_R16G15B16: {
9405  nk_ushort col[3];
9406  col[0] = (nk_ushort)(val[0]*(float)NK_USHORT_MAX);
9407  col[1] = (nk_ushort)(val[1]*(float)NK_USHORT_MAX);
9408  col[2] = (nk_ushort)(val[2]*(float)NK_USHORT_MAX);
9409  NK_MEMCPY(attr, col, sizeof(col));
9410  } break;
9411  case NK_FORMAT_R16G15B16A16: {
9412  nk_ushort col[4];
9413  col[0] = (nk_ushort)(val[0]*(float)NK_USHORT_MAX);
9414  col[1] = (nk_ushort)(val[1]*(float)NK_USHORT_MAX);
9415  col[2] = (nk_ushort)(val[2]*(float)NK_USHORT_MAX);
9416  col[3] = (nk_ushort)(val[3]*(float)NK_USHORT_MAX);
9417  NK_MEMCPY(attr, col, sizeof(col));
9418  } break;
9419  case NK_FORMAT_R32G32B32: {
9420  nk_uint col[3];
9421  col[0] = (nk_uint)(val[0]*(float)NK_UINT_MAX);
9422  col[1] = (nk_uint)(val[1]*(float)NK_UINT_MAX);
9423  col[2] = (nk_uint)(val[2]*(float)NK_UINT_MAX);
9424  NK_MEMCPY(attr, col, sizeof(col));
9425  } break;
9426  case NK_FORMAT_R32G32B32A32: {
9427  nk_uint col[4];
9428  col[0] = (nk_uint)(val[0]*(float)NK_UINT_MAX);
9429  col[1] = (nk_uint)(val[1]*(float)NK_UINT_MAX);
9430  col[2] = (nk_uint)(val[2]*(float)NK_UINT_MAX);
9431  col[3] = (nk_uint)(val[3]*(float)NK_UINT_MAX);
9432  NK_MEMCPY(attr, col, sizeof(col));
9433  } break;
9434  case NK_FORMAT_R32G32B32A32_FLOAT:
9435  NK_MEMCPY(attr, val, sizeof(float)*4);
9436  break;
9437  case NK_FORMAT_R32G32B32A32_DOUBLE: {
9438  double col[4];
9439  col[0] = (double)val[0];
9440  col[1] = (double)val[1];
9441  col[2] = (double)val[2];
9442  col[3] = (double)val[3];
9443  NK_MEMCPY(attr, col, sizeof(col));
9444  } break;
9445  case NK_FORMAT_RGB32:
9446  case NK_FORMAT_RGBA32: {
9447  struct nk_color col = nk_rgba_fv(val);
9448  nk_uint color = nk_color_u32(col);
9449  NK_MEMCPY(attr, &color, sizeof(color));
9450  } break; }
9451 }
9452 NK_INTERN void
9453 nk_draw_vertex_element(void *dst, const float *values, int value_count,
9454  enum nk_draw_vertex_layout_format format)
9455 {
9456  int value_index;
9457  void *attribute = dst;
9458  /* if this triggers you tried to provide a color format for a value */
9459  NK_ASSERT(format < NK_FORMAT_COLOR_BEGIN);
9460  if (format >= NK_FORMAT_COLOR_BEGIN && format <= NK_FORMAT_COLOR_END) return;
9461  for (value_index = 0; value_index < value_count; ++value_index) {
9462  switch (format) {
9463  default: NK_ASSERT(0 && "invalid vertex layout format"); break;
9464  case NK_FORMAT_SCHAR: {
9465  char value = (char)NK_CLAMP((float)NK_SCHAR_MIN, values[value_index], (float)NK_SCHAR_MAX);
9466  NK_MEMCPY(attribute, &value, sizeof(value));
9467  attribute = (void*)((char*)attribute + sizeof(char));
9468  } break;
9469  case NK_FORMAT_SSHORT: {
9470  nk_short value = (nk_short)NK_CLAMP((float)NK_SSHORT_MIN, values[value_index], (float)NK_SSHORT_MAX);
9471  NK_MEMCPY(attribute, &value, sizeof(value));
9472  attribute = (void*)((char*)attribute + sizeof(value));
9473  } break;
9474  case NK_FORMAT_SINT: {
9475  nk_int value = (nk_int)NK_CLAMP((float)NK_SINT_MIN, values[value_index], (float)NK_SINT_MAX);
9476  NK_MEMCPY(attribute, &value, sizeof(value));
9477  attribute = (void*)((char*)attribute + sizeof(nk_int));
9478  } break;
9479  case NK_FORMAT_UCHAR: {
9480  unsigned char value = (unsigned char)NK_CLAMP((float)NK_UCHAR_MIN, values[value_index], (float)NK_UCHAR_MAX);
9481  NK_MEMCPY(attribute, &value, sizeof(value));
9482  attribute = (void*)((char*)attribute + sizeof(unsigned char));
9483  } break;
9484  case NK_FORMAT_USHORT: {
9485  nk_ushort value = (nk_ushort)NK_CLAMP((float)NK_USHORT_MIN, values[value_index], (float)NK_USHORT_MAX);
9486  NK_MEMCPY(attribute, &value, sizeof(value));
9487  attribute = (void*)((char*)attribute + sizeof(value));
9488  } break;
9489  case NK_FORMAT_UINT: {
9490  nk_uint value = (nk_uint)NK_CLAMP((float)NK_UINT_MIN, values[value_index], (float)NK_UINT_MAX);
9491  NK_MEMCPY(attribute, &value, sizeof(value));
9492  attribute = (void*)((char*)attribute + sizeof(nk_uint));
9493  } break;
9494  case NK_FORMAT_FLOAT:
9495  NK_MEMCPY(attribute, &values[value_index], sizeof(values[value_index]));
9496  attribute = (void*)((char*)attribute + sizeof(float));
9497  break;
9498  case NK_FORMAT_DOUBLE: {
9499  double value = (double)values[value_index];
9500  NK_MEMCPY(attribute, &value, sizeof(value));
9501  attribute = (void*)((char*)attribute + sizeof(double));
9502  } break;
9503  }
9504  }
9505 }
9506 NK_INTERN void*
9507 nk_draw_vertex(void *dst, const struct nk_convert_config *config,
9508  struct nk_vec2 pos, struct nk_vec2 uv, struct nk_colorf color)
9509 {
9510  void *result = (void*)((char*)dst + config->vertex_size);
9511  const struct nk_draw_vertex_layout_element *elem_iter = config->vertex_layout;
9512  while (!nk_draw_vertex_layout_element_is_end_of_layout(elem_iter)) {
9513  void *address = (void*)((char*)dst + elem_iter->offset);
9514  switch (elem_iter->attribute) {
9515  case NK_VERTEX_ATTRIBUTE_COUNT:
9516  default: NK_ASSERT(0 && "wrong element attribute"); break;
9517  case NK_VERTEX_POSITION: nk_draw_vertex_element(address, &pos.x, 2, elem_iter->format); break;
9518  case NK_VERTEX_TEXCOORD: nk_draw_vertex_element(address, &uv.x, 2, elem_iter->format); break;
9519  case NK_VERTEX_COLOR: nk_draw_vertex_color(address, &color.r, elem_iter->format); break;
9520  }
9521  elem_iter++;
9522  }
9523  return result;
9524 }
9525 NK_API void
9526 nk_draw_list_stroke_poly_line(struct nk_draw_list *list, const struct nk_vec2 *points,
9527  const unsigned int points_count, struct nk_color color, enum nk_draw_list_stroke closed,
9528  float thickness, enum nk_anti_aliasing aliasing)
9529 {
9530  nk_size count;
9531  int thick_line;
9532  struct nk_colorf col;
9533  struct nk_colorf col_trans;
9534  NK_ASSERT(list);
9535  if (!list || points_count < 2) return;
9536 
9537  color.a = (nk_byte)((float)color.a * list->config.global_alpha);
9538  count = points_count;
9539  if (!closed) count = points_count-1;
9540  thick_line = thickness > 1.0f;
9541 
9542 #ifdef NK_INCLUDE_COMMAND_USERDATA
9543  nk_draw_list_push_userdata(list, list->userdata);
9544 #endif
9545 
9546  color.a = (nk_byte)((float)color.a * list->config.global_alpha);
9547  nk_color_fv(&col.r, color);
9548  col_trans = col;
9549  col_trans.a = 0;
9550 
9551  if (aliasing == NK_ANTI_ALIASING_ON) {
9552  /* ANTI-ALIASED STROKE */
9553  const float AA_SIZE = 1.0f;
9554  NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2);
9555  NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2);
9556 
9557  /* allocate vertices and elements */
9558  nk_size i1 = 0;
9559  nk_size vertex_offset;
9560  nk_size index = list->vertex_count;
9561 
9562  const nk_size idx_count = (thick_line) ? (count * 18) : (count * 12);
9563  const nk_size vtx_count = (thick_line) ? (points_count * 4): (points_count *3);
9564 
9565  void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
9566  nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
9567 
9568  nk_size size;
9569  struct nk_vec2 *normals, *temp;
9570  if (!vtx || !ids) return;
9571 
9572  /* temporary allocate normals + points */
9573  vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr);
9574  nk_buffer_mark(list->vertices, NK_BUFFER_FRONT);
9575  size = pnt_size * ((thick_line) ? 5 : 3) * points_count;
9576  normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align);
9577  if (!normals) return;
9578  temp = normals + points_count;
9579 
9580  /* make sure vertex pointer is still correct */
9581  vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset);
9582 
9583  /* calculate normals */
9584  for (i1 = 0; i1 < count; ++i1) {
9585  const nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1);
9586  struct nk_vec2 diff = nk_vec2_sub(points[i2], points[i1]);
9587  float len;
9588 
9589  /* vec2 inverted length */
9590  len = nk_vec2_len_sqr(diff);
9591  if (len != 0.0f)
9592  len = nk_inv_sqrt(len);
9593  else len = 1.0f;
9594 
9595  diff = nk_vec2_muls(diff, len);
9596  normals[i1].x = diff.y;
9597  normals[i1].y = -diff.x;
9598  }
9599 
9600  if (!closed)
9601  normals[points_count-1] = normals[points_count-2];
9602 
9603  if (!thick_line) {
9604  nk_size idx1, i;
9605  if (!closed) {
9606  struct nk_vec2 d;
9607  temp[0] = nk_vec2_add(points[0], nk_vec2_muls(normals[0], AA_SIZE));
9608  temp[1] = nk_vec2_sub(points[0], nk_vec2_muls(normals[0], AA_SIZE));
9609  d = nk_vec2_muls(normals[points_count-1], AA_SIZE);
9610  temp[(points_count-1) * 2 + 0] = nk_vec2_add(points[points_count-1], d);
9611  temp[(points_count-1) * 2 + 1] = nk_vec2_sub(points[points_count-1], d);
9612  }
9613 
9614  /* fill elements */
9615  idx1 = index;
9616  for (i1 = 0; i1 < count; i1++) {
9617  struct nk_vec2 dm;
9618  float dmr2;
9619  nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1);
9620  nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 3);
9621 
9622  /* average normals */
9623  dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f);
9624  dmr2 = dm.x * dm.x + dm.y* dm.y;
9625  if (dmr2 > 0.000001f) {
9626  float scale = 1.0f/dmr2;
9627  scale = NK_MIN(100.0f, scale);
9628  dm = nk_vec2_muls(dm, scale);
9629  }
9630 
9631  dm = nk_vec2_muls(dm, AA_SIZE);
9632  temp[i2*2+0] = nk_vec2_add(points[i2], dm);
9633  temp[i2*2+1] = nk_vec2_sub(points[i2], dm);
9634 
9635  ids[0] = (nk_draw_index)(idx2 + 0); ids[1] = (nk_draw_index)(idx1+0);
9636  ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2);
9637  ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+0);
9638  ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1);
9639  ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0);
9640  ids[10]= (nk_draw_index)(idx2 + 0); ids[11]= (nk_draw_index)(idx2+1);
9641  ids += 12;
9642  idx1 = idx2;
9643  }
9644 
9645  /* fill vertices */
9646  for (i = 0; i < points_count; ++i) {
9647  const struct nk_vec2 uv = list->config.null.uv;
9648  vtx = nk_draw_vertex(vtx, &list->config, points[i], uv, col);
9649  vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+0], uv, col_trans);
9650  vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+1], uv, col_trans);
9651  }
9652  } else {
9653  nk_size idx1, i;
9654  const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f;
9655  if (!closed) {
9656  struct nk_vec2 d1 = nk_vec2_muls(normals[0], half_inner_thickness + AA_SIZE);
9657  struct nk_vec2 d2 = nk_vec2_muls(normals[0], half_inner_thickness);
9658 
9659  temp[0] = nk_vec2_add(points[0], d1);
9660  temp[1] = nk_vec2_add(points[0], d2);
9661  temp[2] = nk_vec2_sub(points[0], d2);
9662  temp[3] = nk_vec2_sub(points[0], d1);
9663 
9664  d1 = nk_vec2_muls(normals[points_count-1], half_inner_thickness + AA_SIZE);
9665  d2 = nk_vec2_muls(normals[points_count-1], half_inner_thickness);
9666 
9667  temp[(points_count-1)*4+0] = nk_vec2_add(points[points_count-1], d1);
9668  temp[(points_count-1)*4+1] = nk_vec2_add(points[points_count-1], d2);
9669  temp[(points_count-1)*4+2] = nk_vec2_sub(points[points_count-1], d2);
9670  temp[(points_count-1)*4+3] = nk_vec2_sub(points[points_count-1], d1);
9671  }
9672 
9673  /* add all elements */
9674  idx1 = index;
9675  for (i1 = 0; i1 < count; ++i1) {
9676  struct nk_vec2 dm_out, dm_in;
9677  const nk_size i2 = ((i1+1) == points_count) ? 0: (i1 + 1);
9678  nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 4);
9679 
9680  /* average normals */
9681  struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f);
9682  float dmr2 = dm.x * dm.x + dm.y* dm.y;
9683  if (dmr2 > 0.000001f) {
9684  float scale = 1.0f/dmr2;
9685  scale = NK_MIN(100.0f, scale);
9686  dm = nk_vec2_muls(dm, scale);
9687  }
9688 
9689  dm_out = nk_vec2_muls(dm, ((half_inner_thickness) + AA_SIZE));
9690  dm_in = nk_vec2_muls(dm, half_inner_thickness);
9691  temp[i2*4+0] = nk_vec2_add(points[i2], dm_out);
9692  temp[i2*4+1] = nk_vec2_add(points[i2], dm_in);
9693  temp[i2*4+2] = nk_vec2_sub(points[i2], dm_in);
9694  temp[i2*4+3] = nk_vec2_sub(points[i2], dm_out);
9695 
9696  /* add indexes */
9697  ids[0] = (nk_draw_index)(idx2 + 1); ids[1] = (nk_draw_index)(idx1+1);
9698  ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2);
9699  ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+1);
9700  ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1);
9701  ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0);
9702  ids[10]= (nk_draw_index)(idx2 + 0); ids[11] = (nk_draw_index)(idx2+1);
9703  ids[12]= (nk_draw_index)(idx2 + 2); ids[13] = (nk_draw_index)(idx1+2);
9704  ids[14]= (nk_draw_index)(idx1 + 3); ids[15] = (nk_draw_index)(idx1+3);
9705  ids[16]= (nk_draw_index)(idx2 + 3); ids[17] = (nk_draw_index)(idx2+2);
9706  ids += 18;
9707  idx1 = idx2;
9708  }
9709 
9710  /* add vertices */
9711  for (i = 0; i < points_count; ++i) {
9712  const struct nk_vec2 uv = list->config.null.uv;
9713  vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+0], uv, col_trans);
9714  vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+1], uv, col);
9715  vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+2], uv, col);
9716  vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+3], uv, col_trans);
9717  }
9718  }
9719  /* free temporary normals + points */
9720  nk_buffer_reset(list->vertices, NK_BUFFER_FRONT);
9721  } else {
9722  /* NON ANTI-ALIASED STROKE */
9723  nk_size i1 = 0;
9724  nk_size idx = list->vertex_count;
9725  const nk_size idx_count = count * 6;
9726  const nk_size vtx_count = count * 4;
9727  void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
9728  nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
9729  if (!vtx || !ids) return;
9730 
9731  for (i1 = 0; i1 < count; ++i1) {
9732  float dx, dy;
9733  const struct nk_vec2 uv = list->config.null.uv;
9734  const nk_size i2 = ((i1+1) == points_count) ? 0 : i1 + 1;
9735  const struct nk_vec2 p1 = points[i1];
9736  const struct nk_vec2 p2 = points[i2];
9737  struct nk_vec2 diff = nk_vec2_sub(p2, p1);
9738  float len;
9739 
9740  /* vec2 inverted length */
9741  len = nk_vec2_len_sqr(diff);
9742  if (len != 0.0f)
9743  len = nk_inv_sqrt(len);
9744  else len = 1.0f;
9745  diff = nk_vec2_muls(diff, len);
9746 
9747  /* add vertices */
9748  dx = diff.x * (thickness * 0.5f);
9749  dy = diff.y * (thickness * 0.5f);
9750 
9751  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x + dy, p1.y - dx), uv, col);
9752  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x + dy, p2.y - dx), uv, col);
9753  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x - dy, p2.y + dx), uv, col);
9754  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x - dy, p1.y + dx), uv, col);
9755 
9756  ids[0] = (nk_draw_index)(idx+0); ids[1] = (nk_draw_index)(idx+1);
9757  ids[2] = (nk_draw_index)(idx+2); ids[3] = (nk_draw_index)(idx+0);
9758  ids[4] = (nk_draw_index)(idx+2); ids[5] = (nk_draw_index)(idx+3);
9759 
9760  ids += 6;
9761  idx += 4;
9762  }
9763  }
9764 }
9765 NK_API void
9766 nk_draw_list_fill_poly_convex(struct nk_draw_list *list,
9767  const struct nk_vec2 *points, const unsigned int points_count,
9768  struct nk_color color, enum nk_anti_aliasing aliasing)
9769 {
9770  struct nk_colorf col;
9771  struct nk_colorf col_trans;
9772 
9773  NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2);
9774  NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2);
9775  NK_ASSERT(list);
9776  if (!list || points_count < 3) return;
9777 
9778 #ifdef NK_INCLUDE_COMMAND_USERDATA
9779  nk_draw_list_push_userdata(list, list->userdata);
9780 #endif
9781 
9782  color.a = (nk_byte)((float)color.a * list->config.global_alpha);
9783  nk_color_fv(&col.r, color);
9784  col_trans = col;
9785  col_trans.a = 0;
9786 
9787  if (aliasing == NK_ANTI_ALIASING_ON) {
9788  nk_size i = 0;
9789  nk_size i0 = 0;
9790  nk_size i1 = 0;
9791 
9792  const float AA_SIZE = 1.0f;
9793  nk_size vertex_offset = 0;
9794  nk_size index = list->vertex_count;
9795 
9796  const nk_size idx_count = (points_count-2)*3 + points_count*6;
9797  const nk_size vtx_count = (points_count*2);
9798 
9799  void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
9800  nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
9801 
9802  nk_size size = 0;
9803  struct nk_vec2 *normals = 0;
9804  unsigned int vtx_inner_idx = (unsigned int)(index + 0);
9805  unsigned int vtx_outer_idx = (unsigned int)(index + 1);
9806  if (!vtx || !ids) return;
9807 
9808  /* temporary allocate normals */
9809  vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr);
9810  nk_buffer_mark(list->vertices, NK_BUFFER_FRONT);
9811  size = pnt_size * points_count;
9812  normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align);
9813  if (!normals) return;
9814  vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset);
9815 
9816  /* add elements */
9817  for (i = 2; i < points_count; i++) {
9818  ids[0] = (nk_draw_index)(vtx_inner_idx);
9819  ids[1] = (nk_draw_index)(vtx_inner_idx + ((i-1) << 1));
9820  ids[2] = (nk_draw_index)(vtx_inner_idx + (i << 1));
9821  ids += 3;
9822  }
9823 
9824  /* compute normals */
9825  for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) {
9826  struct nk_vec2 p0 = points[i0];
9827  struct nk_vec2 p1 = points[i1];
9828  struct nk_vec2 diff = nk_vec2_sub(p1, p0);
9829 
9830  /* vec2 inverted length */
9831  float len = nk_vec2_len_sqr(diff);
9832  if (len != 0.0f)
9833  len = nk_inv_sqrt(len);
9834  else len = 1.0f;
9835  diff = nk_vec2_muls(diff, len);
9836 
9837  normals[i0].x = diff.y;
9838  normals[i0].y = -diff.x;
9839  }
9840 
9841  /* add vertices + indexes */
9842  for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) {
9843  const struct nk_vec2 uv = list->config.null.uv;
9844  struct nk_vec2 n0 = normals[i0];
9845  struct nk_vec2 n1 = normals[i1];
9846  struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(n0, n1), 0.5f);
9847  float dmr2 = dm.x*dm.x + dm.y*dm.y;
9848  if (dmr2 > 0.000001f) {
9849  float scale = 1.0f / dmr2;
9850  scale = NK_MIN(scale, 100.0f);
9851  dm = nk_vec2_muls(dm, scale);
9852  }
9853  dm = nk_vec2_muls(dm, AA_SIZE * 0.5f);
9854 
9855  /* add vertices */
9856  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_sub(points[i1], dm), uv, col);
9857  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_add(points[i1], dm), uv, col_trans);
9858 
9859  /* add indexes */
9860  ids[0] = (nk_draw_index)(vtx_inner_idx+(i1<<1));
9861  ids[1] = (nk_draw_index)(vtx_inner_idx+(i0<<1));
9862  ids[2] = (nk_draw_index)(vtx_outer_idx+(i0<<1));
9863  ids[3] = (nk_draw_index)(vtx_outer_idx+(i0<<1));
9864  ids[4] = (nk_draw_index)(vtx_outer_idx+(i1<<1));
9865  ids[5] = (nk_draw_index)(vtx_inner_idx+(i1<<1));
9866  ids += 6;
9867  }
9868  /* free temporary normals + points */
9869  nk_buffer_reset(list->vertices, NK_BUFFER_FRONT);
9870  } else {
9871  nk_size i = 0;
9872  nk_size index = list->vertex_count;
9873  const nk_size idx_count = (points_count-2)*3;
9874  const nk_size vtx_count = points_count;
9875  void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
9876  nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
9877 
9878  if (!vtx || !ids) return;
9879  for (i = 0; i < vtx_count; ++i)
9880  vtx = nk_draw_vertex(vtx, &list->config, points[i], list->config.null.uv, col);
9881  for (i = 2; i < points_count; ++i) {
9882  ids[0] = (nk_draw_index)index;
9883  ids[1] = (nk_draw_index)(index+ i - 1);
9884  ids[2] = (nk_draw_index)(index+i);
9885  ids += 3;
9886  }
9887  }
9888 }
9889 NK_API void
9890 nk_draw_list_path_clear(struct nk_draw_list *list)
9891 {
9892  NK_ASSERT(list);
9893  if (!list) return;
9894  nk_buffer_reset(list->buffer, NK_BUFFER_FRONT);
9895  list->path_count = 0;
9896  list->path_offset = 0;
9897 }
9898 NK_API void
9899 nk_draw_list_path_line_to(struct nk_draw_list *list, struct nk_vec2 pos)
9900 {
9901  struct nk_vec2 *points = 0;
9902  struct nk_draw_command *cmd = 0;
9903  NK_ASSERT(list);
9904  if (!list) return;
9905  if (!list->cmd_count)
9906  nk_draw_list_add_clip(list, nk_null_rect);
9907 
9908  cmd = nk_draw_list_command_last(list);
9909  if (cmd && cmd->texture.ptr != list->config.null.texture.ptr)
9910  nk_draw_list_push_image(list, list->config.null.texture);
9911 
9912  points = nk_draw_list_alloc_path(list, 1);
9913  if (!points) return;
9914  points[0] = pos;
9915 }
9916 NK_API void
9917 nk_draw_list_path_arc_to_fast(struct nk_draw_list *list, struct nk_vec2 center,
9918  float radius, int a_min, int a_max)
9919 {
9920  int a = 0;
9921  NK_ASSERT(list);
9922  if (!list) return;
9923  if (a_min <= a_max) {
9924  for (a = a_min; a <= a_max; a++) {
9925  const struct nk_vec2 c = list->circle_vtx[(nk_size)a % NK_LEN(list->circle_vtx)];
9926  const float x = center.x + c.x * radius;
9927  const float y = center.y + c.y * radius;
9928  nk_draw_list_path_line_to(list, nk_vec2(x, y));
9929  }
9930  }
9931 }
9932 NK_API void
9933 nk_draw_list_path_arc_to(struct nk_draw_list *list, struct nk_vec2 center,
9934  float radius, float a_min, float a_max, unsigned int segments)
9935 {
9936  unsigned int i = 0;
9937  NK_ASSERT(list);
9938  if (!list) return;
9939  if (radius == 0.0f) return;
9940 
9941  /* This algorithm for arc drawing relies on these two trigonometric identities[1]:
9942  sin(a + b) = sin(a) * cos(b) + cos(a) * sin(b)
9943  cos(a + b) = cos(a) * cos(b) - sin(a) * sin(b)
9944 
9945  Two coordinates (x, y) of a point on a circle centered on
9946  the origin can be written in polar form as:
9947  x = r * cos(a)
9948  y = r * sin(a)
9949  where r is the radius of the circle,
9950  a is the angle between (x, y) and the origin.
9951 
9952  This allows us to rotate the coordinates around the
9953  origin by an angle b using the following transformation:
9954  x' = r * cos(a + b) = x * cos(b) - y * sin(b)
9955  y' = r * sin(a + b) = y * cos(b) + x * sin(b)
9956 
9957  [1] https://en.wikipedia.org/wiki/List_of_trigonometric_identities#Angle_sum_and_difference_identities
9958  */
9959  {const float d_angle = (a_max - a_min) / (float)segments;
9960  const float sin_d = (float)NK_SIN(d_angle);
9961  const float cos_d = (float)NK_COS(d_angle);
9962 
9963  float cx = (float)NK_COS(a_min) * radius;
9964  float cy = (float)NK_SIN(a_min) * radius;
9965  for(i = 0; i <= segments; ++i) {
9966  float new_cx, new_cy;
9967  const float x = center.x + cx;
9968  const float y = center.y + cy;
9969  nk_draw_list_path_line_to(list, nk_vec2(x, y));
9970 
9971  new_cx = cx * cos_d - cy * sin_d;
9972  new_cy = cy * cos_d + cx * sin_d;
9973  cx = new_cx;
9974  cy = new_cy;
9975  }}
9976 }
9977 NK_API void
9978 nk_draw_list_path_rect_to(struct nk_draw_list *list, struct nk_vec2 a,
9979  struct nk_vec2 b, float rounding)
9980 {
9981  float r;
9982  NK_ASSERT(list);
9983  if (!list) return;
9984  r = rounding;
9985  r = NK_MIN(r, ((b.x-a.x) < 0) ? -(b.x-a.x): (b.x-a.x));
9986  r = NK_MIN(r, ((b.y-a.y) < 0) ? -(b.y-a.y): (b.y-a.y));
9987 
9988  if (r == 0.0f) {
9989  nk_draw_list_path_line_to(list, a);
9990  nk_draw_list_path_line_to(list, nk_vec2(b.x,a.y));
9991  nk_draw_list_path_line_to(list, b);
9992  nk_draw_list_path_line_to(list, nk_vec2(a.x,b.y));
9993  } else {
9994  nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, a.y + r), r, 6, 9);
9995  nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, a.y + r), r, 9, 12);
9996  nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, b.y - r), r, 0, 3);
9997  nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, b.y - r), r, 3, 6);
9998  }
9999 }
10000 NK_API void
10001 nk_draw_list_path_curve_to(struct nk_draw_list *list, struct nk_vec2 p2,
10002  struct nk_vec2 p3, struct nk_vec2 p4, unsigned int num_segments)
10003 {
10004  float t_step;
10005  unsigned int i_step;
10006  struct nk_vec2 p1;
10007 
10008  NK_ASSERT(list);
10009  NK_ASSERT(list->path_count);
10010  if (!list || !list->path_count) return;
10011  num_segments = NK_MAX(num_segments, 1);
10012 
10013  p1 = nk_draw_list_path_last(list);
10014  t_step = 1.0f/(float)num_segments;
10015  for (i_step = 1; i_step <= num_segments; ++i_step) {
10016  float t = t_step * (float)i_step;
10017  float u = 1.0f - t;
10018  float w1 = u*u*u;
10019  float w2 = 3*u*u*t;
10020  float w3 = 3*u*t*t;
10021  float w4 = t * t *t;
10022  float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x;
10023  float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y;
10024  nk_draw_list_path_line_to(list, nk_vec2(x,y));
10025  }
10026 }
10027 NK_API void
10028 nk_draw_list_path_fill(struct nk_draw_list *list, struct nk_color color)
10029 {
10030  struct nk_vec2 *points;
10031  NK_ASSERT(list);
10032  if (!list) return;
10033  points = (struct nk_vec2*)nk_buffer_memory(list->buffer);
10034  nk_draw_list_fill_poly_convex(list, points, list->path_count, color, list->config.shape_AA);
10035  nk_draw_list_path_clear(list);
10036 }
10037 NK_API void
10038 nk_draw_list_path_stroke(struct nk_draw_list *list, struct nk_color color,
10039  enum nk_draw_list_stroke closed, float thickness)
10040 {
10041  struct nk_vec2 *points;
10042  NK_ASSERT(list);
10043  if (!list) return;
10044  points = (struct nk_vec2*)nk_buffer_memory(list->buffer);
10045  nk_draw_list_stroke_poly_line(list, points, list->path_count, color,
10046  closed, thickness, list->config.line_AA);
10047  nk_draw_list_path_clear(list);
10048 }
10049 NK_API void
10050 nk_draw_list_stroke_line(struct nk_draw_list *list, struct nk_vec2 a,
10051  struct nk_vec2 b, struct nk_color col, float thickness)
10052 {
10053  NK_ASSERT(list);
10054  if (!list || !col.a) return;
10055  if (list->line_AA == NK_ANTI_ALIASING_ON) {
10056  nk_draw_list_path_line_to(list, a);
10057  nk_draw_list_path_line_to(list, b);
10058  } else {
10059  nk_draw_list_path_line_to(list, nk_vec2_sub(a,nk_vec2(0.5f,0.5f)));
10060  nk_draw_list_path_line_to(list, nk_vec2_sub(b,nk_vec2(0.5f,0.5f)));
10061  }
10062  nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness);
10063 }
10064 NK_API void
10065 nk_draw_list_fill_rect(struct nk_draw_list *list, struct nk_rect rect,
10066  struct nk_color col, float rounding)
10067 {
10068  NK_ASSERT(list);
10069  if (!list || !col.a) return;
10070 
10071  if (list->line_AA == NK_ANTI_ALIASING_ON) {
10072  nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y),
10073  nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
10074  } else {
10075  nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f),
10076  nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
10077  } nk_draw_list_path_fill(list, col);
10078 }
10079 NK_API void
10080 nk_draw_list_stroke_rect(struct nk_draw_list *list, struct nk_rect rect,
10081  struct nk_color col, float rounding, float thickness)
10082 {
10083  NK_ASSERT(list);
10084  if (!list || !col.a) return;
10085  if (list->line_AA == NK_ANTI_ALIASING_ON) {
10086  nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y),
10087  nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
10088  } else {
10089  nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f),
10090  nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
10091  } nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
10092 }
10093 NK_API void
10094 nk_draw_list_fill_rect_multi_color(struct nk_draw_list *list, struct nk_rect rect,
10095  struct nk_color left, struct nk_color top, struct nk_color right,
10096  struct nk_color bottom)
10097 {
10098  void *vtx;
10099  struct nk_colorf col_left, col_top;
10100  struct nk_colorf col_right, col_bottom;
10101  nk_draw_index *idx;
10102  nk_draw_index index;
10103 
10104  nk_color_fv(&col_left.r, left);
10105  nk_color_fv(&col_right.r, right);
10106  nk_color_fv(&col_top.r, top);
10107  nk_color_fv(&col_bottom.r, bottom);
10108 
10109  NK_ASSERT(list);
10110  if (!list) return;
10111 
10112  nk_draw_list_push_image(list, list->config.null.texture);
10113  index = (nk_draw_index)list->vertex_count;
10114  vtx = nk_draw_list_alloc_vertices(list, 4);
10115  idx = nk_draw_list_alloc_elements(list, 6);
10116  if (!vtx || !idx) return;
10117 
10118  idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1);
10119  idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0);
10120  idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3);
10121 
10122  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y), list->config.null.uv, col_left);
10123  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y), list->config.null.uv, col_top);
10124  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y + rect.h), list->config.null.uv, col_right);
10125  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y + rect.h), list->config.null.uv, col_bottom);
10126 }
10127 NK_API void
10128 nk_draw_list_fill_triangle(struct nk_draw_list *list, struct nk_vec2 a,
10129  struct nk_vec2 b, struct nk_vec2 c, struct nk_color col)
10130 {
10131  NK_ASSERT(list);
10132  if (!list || !col.a) return;
10133  nk_draw_list_path_line_to(list, a);
10134  nk_draw_list_path_line_to(list, b);
10135  nk_draw_list_path_line_to(list, c);
10136  nk_draw_list_path_fill(list, col);
10137 }
10138 NK_API void
10139 nk_draw_list_stroke_triangle(struct nk_draw_list *list, struct nk_vec2 a,
10140  struct nk_vec2 b, struct nk_vec2 c, struct nk_color col, float thickness)
10141 {
10142  NK_ASSERT(list);
10143  if (!list || !col.a) return;
10144  nk_draw_list_path_line_to(list, a);
10145  nk_draw_list_path_line_to(list, b);
10146  nk_draw_list_path_line_to(list, c);
10147  nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
10148 }
10149 NK_API void
10150 nk_draw_list_fill_circle(struct nk_draw_list *list, struct nk_vec2 center,
10151  float radius, struct nk_color col, unsigned int segs)
10152 {
10153  float a_max;
10154  NK_ASSERT(list);
10155  if (!list || !col.a) return;
10156  a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs;
10157  nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs);
10158  nk_draw_list_path_fill(list, col);
10159 }
10160 NK_API void
10161 nk_draw_list_stroke_circle(struct nk_draw_list *list, struct nk_vec2 center,
10162  float radius, struct nk_color col, unsigned int segs, float thickness)
10163 {
10164  float a_max;
10165  NK_ASSERT(list);
10166  if (!list || !col.a) return;
10167  a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs;
10168  nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs);
10169  nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
10170 }
10171 NK_API void
10172 nk_draw_list_stroke_curve(struct nk_draw_list *list, struct nk_vec2 p0,
10173  struct nk_vec2 cp0, struct nk_vec2 cp1, struct nk_vec2 p1,
10174  struct nk_color col, unsigned int segments, float thickness)
10175 {
10176  NK_ASSERT(list);
10177  if (!list || !col.a) return;
10178  nk_draw_list_path_line_to(list, p0);
10179  nk_draw_list_path_curve_to(list, cp0, cp1, p1, segments);
10180  nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness);
10181 }
10182 NK_INTERN void
10183 nk_draw_list_push_rect_uv(struct nk_draw_list *list, struct nk_vec2 a,
10184  struct nk_vec2 c, struct nk_vec2 uva, struct nk_vec2 uvc,
10185  struct nk_color color)
10186 {
10187  void *vtx;
10188  struct nk_vec2 uvb;
10189  struct nk_vec2 uvd;
10190  struct nk_vec2 b;
10191  struct nk_vec2 d;
10192 
10193  struct nk_colorf col;
10194  nk_draw_index *idx;
10195  nk_draw_index index;
10196  NK_ASSERT(list);
10197  if (!list) return;
10198 
10199  nk_color_fv(&col.r, color);
10200  uvb = nk_vec2(uvc.x, uva.y);
10201  uvd = nk_vec2(uva.x, uvc.y);
10202  b = nk_vec2(c.x, a.y);
10203  d = nk_vec2(a.x, c.y);
10204 
10205  index = (nk_draw_index)list->vertex_count;
10206  vtx = nk_draw_list_alloc_vertices(list, 4);
10207  idx = nk_draw_list_alloc_elements(list, 6);
10208  if (!vtx || !idx) return;
10209 
10210  idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1);
10211  idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0);
10212  idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3);
10213 
10214  vtx = nk_draw_vertex(vtx, &list->config, a, uva, col);
10215  vtx = nk_draw_vertex(vtx, &list->config, b, uvb, col);
10216  vtx = nk_draw_vertex(vtx, &list->config, c, uvc, col);
10217  vtx = nk_draw_vertex(vtx, &list->config, d, uvd, col);
10218 }
10219 NK_API void
10220 nk_draw_list_add_image(struct nk_draw_list *list, struct nk_image texture,
10221  struct nk_rect rect, struct nk_color color)
10222 {
10223  NK_ASSERT(list);
10224  if (!list) return;
10225  /* push new command with given texture */
10226  nk_draw_list_push_image(list, texture.handle);
10227  if (nk_image_is_subimage(&texture)) {
10228  /* add region inside of the texture */
10229  struct nk_vec2 uv[2];
10230  uv[0].x = (float)texture.region[0]/(float)texture.w;
10231  uv[0].y = (float)texture.region[1]/(float)texture.h;
10232  uv[1].x = (float)(texture.region[0] + texture.region[2])/(float)texture.w;
10233  uv[1].y = (float)(texture.region[1] + texture.region[3])/(float)texture.h;
10234  nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y),
10235  nk_vec2(rect.x + rect.w, rect.y + rect.h), uv[0], uv[1], color);
10236  } else nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y),
10237  nk_vec2(rect.x + rect.w, rect.y + rect.h),
10238  nk_vec2(0.0f, 0.0f), nk_vec2(1.0f, 1.0f),color);
10239 }
10240 NK_API void
10241 nk_draw_list_add_text(struct nk_draw_list *list, const struct nk_user_font *font,
10242  struct nk_rect rect, const char *text, int len, float font_height,
10243  struct nk_color fg)
10244 {
10245  float x = 0;
10246  int text_len = 0;
10247  nk_rune unicode = 0;
10248  nk_rune next = 0;
10249  int glyph_len = 0;
10250  int next_glyph_len = 0;
10251  struct nk_user_font_glyph g;
10252 
10253  NK_ASSERT(list);
10254  if (!list || !len || !text) return;
10255  if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
10256  list->clip_rect.x, list->clip_rect.y, list->clip_rect.w, list->clip_rect.h)) return;
10257 
10258  nk_draw_list_push_image(list, font->texture);
10259  x = rect.x;
10260  glyph_len = nk_utf_decode(text, &unicode, len);
10261  if (!glyph_len) return;
10262 
10263  /* draw every glyph image */
10264  fg.a = (nk_byte)((float)fg.a * list->config.global_alpha);
10265  while (text_len < len && glyph_len) {
10266  float gx, gy, gh, gw;
10267  float char_width = 0;
10268  if (unicode == NK_UTF_INVALID) break;
10269 
10270  /* query currently drawn glyph information */
10271  next_glyph_len = nk_utf_decode(text + text_len + glyph_len, &next, (int)len - text_len);
10272  font->query(font->userdata, font_height, &g, unicode,
10273  (next == NK_UTF_INVALID) ? '\0' : next);
10274 
10275  /* calculate and draw glyph drawing rectangle and image */
10276  gx = x + g.offset.x;
10277  gy = rect.y + g.offset.y;
10278  gw = g.width; gh = g.height;
10279  char_width = g.xadvance;
10280  nk_draw_list_push_rect_uv(list, nk_vec2(gx,gy), nk_vec2(gx + gw, gy+ gh),
10281  g.uv[0], g.uv[1], fg);
10282 
10283  /* offset next glyph */
10284  text_len += glyph_len;
10285  x += char_width;
10286  glyph_len = next_glyph_len;
10287  unicode = next;
10288  }
10289 }
10291 nk_convert(struct nk_context *ctx, struct nk_buffer *cmds,
10292  struct nk_buffer *vertices, struct nk_buffer *elements,
10293  const struct nk_convert_config *config)
10294 {
10296  const struct nk_command *cmd;
10297  NK_ASSERT(ctx);
10298  NK_ASSERT(cmds);
10299  NK_ASSERT(vertices);
10300  NK_ASSERT(elements);
10301  NK_ASSERT(config);
10302  NK_ASSERT(config->vertex_layout);
10303  NK_ASSERT(config->vertex_size);
10304  if (!ctx || !cmds || !vertices || !elements || !config || !config->vertex_layout)
10305  return NK_CONVERT_INVALID_PARAM;
10306 
10307  nk_draw_list_setup(&ctx->draw_list, config, cmds, vertices, elements,
10308  config->line_AA, config->shape_AA);
10309  nk_foreach(cmd, ctx)
10310  {
10311 #ifdef NK_INCLUDE_COMMAND_USERDATA
10312  ctx->draw_list.userdata = cmd->userdata;
10313 #endif
10314  switch (cmd->type) {
10315  case NK_COMMAND_NOP: break;
10316  case NK_COMMAND_SCISSOR: {
10317  const struct nk_command_scissor *s = (const struct nk_command_scissor*)cmd;
10318  nk_draw_list_add_clip(&ctx->draw_list, nk_rect(s->x, s->y, s->w, s->h));
10319  } break;
10320  case NK_COMMAND_LINE: {
10321  const struct nk_command_line *l = (const struct nk_command_line*)cmd;
10322  nk_draw_list_stroke_line(&ctx->draw_list, nk_vec2(l->begin.x, l->begin.y),
10323  nk_vec2(l->end.x, l->end.y), l->color, l->line_thickness);
10324  } break;
10325  case NK_COMMAND_CURVE: {
10326  const struct nk_command_curve *q = (const struct nk_command_curve*)cmd;
10327  nk_draw_list_stroke_curve(&ctx->draw_list, nk_vec2(q->begin.x, q->begin.y),
10328  nk_vec2(q->ctrl[0].x, q->ctrl[0].y), nk_vec2(q->ctrl[1].x,
10329  q->ctrl[1].y), nk_vec2(q->end.x, q->end.y), q->color,
10330  config->curve_segment_count, q->line_thickness);
10331  } break;
10332  case NK_COMMAND_RECT: {
10333  const struct nk_command_rect *r = (const struct nk_command_rect*)cmd;
10334  nk_draw_list_stroke_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
10335  r->color, (float)r->rounding, r->line_thickness);
10336  } break;
10337  case NK_COMMAND_RECT_FILLED: {
10338  const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled*)cmd;
10339  nk_draw_list_fill_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
10340  r->color, (float)r->rounding);
10341  } break;
10343  const struct nk_command_rect_multi_color *r = (const struct nk_command_rect_multi_color*)cmd;
10344  nk_draw_list_fill_rect_multi_color(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
10345  r->left, r->top, r->right, r->bottom);
10346  } break;
10347  case NK_COMMAND_CIRCLE: {
10348  const struct nk_command_circle *c = (const struct nk_command_circle*)cmd;
10349  nk_draw_list_stroke_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2,
10350  (float)c->y + (float)c->h/2), (float)c->w/2, c->color,
10351  config->circle_segment_count, c->line_thickness);
10352  } break;
10353  case NK_COMMAND_CIRCLE_FILLED: {
10354  const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd;
10355  nk_draw_list_fill_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2,
10356  (float)c->y + (float)c->h/2), (float)c->w/2, c->color,
10357  config->circle_segment_count);
10358  } break;
10359  case NK_COMMAND_ARC: {
10360  const struct nk_command_arc *c = (const struct nk_command_arc*)cmd;
10361  nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy));
10362  nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r,
10363  c->a[0], c->a[1], config->arc_segment_count);
10364  nk_draw_list_path_stroke(&ctx->draw_list, c->color, NK_STROKE_CLOSED, c->line_thickness);
10365  } break;
10366  case NK_COMMAND_ARC_FILLED: {
10367  const struct nk_command_arc_filled *c = (const struct nk_command_arc_filled*)cmd;
10368  nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy));
10369  nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r,
10370  c->a[0], c->a[1], config->arc_segment_count);
10371  nk_draw_list_path_fill(&ctx->draw_list, c->color);
10372  } break;
10373  case NK_COMMAND_TRIANGLE: {
10374  const struct nk_command_triangle *t = (const struct nk_command_triangle*)cmd;
10375  nk_draw_list_stroke_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y),
10376  nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color,
10377  t->line_thickness);
10378  } break;
10380  const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled*)cmd;
10381  nk_draw_list_fill_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y),
10382  nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color);
10383  } break;
10384  case NK_COMMAND_POLYGON: {
10385  int i;
10386  const struct nk_command_polygon*p = (const struct nk_command_polygon*)cmd;
10387  for (i = 0; i < p->point_count; ++i) {
10388  struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
10389  nk_draw_list_path_line_to(&ctx->draw_list, pnt);
10390  }
10391  nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_CLOSED, p->line_thickness);
10392  } break;
10394  int i;
10395  const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled*)cmd;
10396  for (i = 0; i < p->point_count; ++i) {
10397  struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
10398  nk_draw_list_path_line_to(&ctx->draw_list, pnt);
10399  }
10400  nk_draw_list_path_fill(&ctx->draw_list, p->color);
10401  } break;
10402  case NK_COMMAND_POLYLINE: {
10403  int i;
10404  const struct nk_command_polyline *p = (const struct nk_command_polyline*)cmd;
10405  for (i = 0; i < p->point_count; ++i) {
10406  struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
10407  nk_draw_list_path_line_to(&ctx->draw_list, pnt);
10408  }
10409  nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_OPEN, p->line_thickness);
10410  } break;
10411  case NK_COMMAND_TEXT: {
10412  const struct nk_command_text *t = (const struct nk_command_text*)cmd;
10413  nk_draw_list_add_text(&ctx->draw_list, t->font, nk_rect(t->x, t->y, t->w, t->h),
10414  t->string, t->length, t->height, t->foreground);
10415  } break;
10416  case NK_COMMAND_IMAGE: {
10417  const struct nk_command_image *i = (const struct nk_command_image*)cmd;
10418  nk_draw_list_add_image(&ctx->draw_list, i->img, nk_rect(i->x, i->y, i->w, i->h), i->col);
10419  } break;
10420  case NK_COMMAND_CUSTOM: {
10421  const struct nk_command_custom *c = (const struct nk_command_custom*)cmd;
10422  c->callback(&ctx->draw_list, c->x, c->y, c->w, c->h, c->callback_data);
10423  } break;
10424  default: break;
10425  }
10426  }
10427  res |= (cmds->needed > cmds->allocated + (cmds->memory.size - cmds->size)) ? NK_CONVERT_COMMAND_BUFFER_FULL: 0;
10428  res |= (vertices->needed > vertices->allocated) ? NK_CONVERT_VERTEX_BUFFER_FULL: 0;
10429  res |= (elements->needed > elements->allocated) ? NK_CONVERT_ELEMENT_BUFFER_FULL: 0;
10430  return res;
10431 }
10432 NK_API const struct nk_draw_command*
10433 nk__draw_begin(const struct nk_context *ctx,
10434  const struct nk_buffer *buffer)
10435 {
10436  return nk__draw_list_begin(&ctx->draw_list, buffer);
10437 }
10438 NK_API const struct nk_draw_command*
10439 nk__draw_end(const struct nk_context *ctx, const struct nk_buffer *buffer)
10440 {
10441  return nk__draw_list_end(&ctx->draw_list, buffer);
10442 }
10443 NK_API const struct nk_draw_command*
10444 nk__draw_next(const struct nk_draw_command *cmd,
10445  const struct nk_buffer *buffer, const struct nk_context *ctx)
10446 {
10447  return nk__draw_list_next(cmd, buffer, &ctx->draw_list);
10448 }
10449 #endif
10450 
10451 
10452 
10453 
10454 
10455 #ifdef NK_INCLUDE_FONT_BAKING
10456 /* -------------------------------------------------------------
10457  *
10458  * RECT PACK
10459  *
10460  * --------------------------------------------------------------*/
10461 /* stb_rect_pack.h - v0.05 - public domain - rectangle packing */
10462 /* Sean Barrett 2014 */
10463 #define NK_RP__MAXVAL 0xffff
10464 typedef unsigned short nk_rp_coord;
10465 
10466 struct nk_rp_rect {
10467  /* reserved for your use: */
10468  int id;
10469  /* input: */
10470  nk_rp_coord w, h;
10471  /* output: */
10472  nk_rp_coord x, y;
10473  int was_packed;
10474  /* non-zero if valid packing */
10475 }; /* 16 bytes, nominally */
10476 
10477 struct nk_rp_node {
10478  nk_rp_coord x,y;
10479  struct nk_rp_node *next;
10480 };
10481 
10482 struct nk_rp_context {
10483  int width;
10484  int height;
10485  int align;
10486  int init_mode;
10487  int heuristic;
10488  int num_nodes;
10489  struct nk_rp_node *active_head;
10490  struct nk_rp_node *free_head;
10491  struct nk_rp_node extra[2];
10492  /* we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' */
10493 };
10494 
10495 struct nk_rp__findresult {
10496  int x,y;
10497  struct nk_rp_node **prev_link;
10498 };
10499 
10500 enum NK_RP_HEURISTIC {
10501  NK_RP_HEURISTIC_Skyline_default=0,
10502  NK_RP_HEURISTIC_Skyline_BL_sortHeight = NK_RP_HEURISTIC_Skyline_default,
10503  NK_RP_HEURISTIC_Skyline_BF_sortHeight
10504 };
10505 enum NK_RP_INIT_STATE{NK_RP__INIT_skyline = 1};
10506 
10507 NK_INTERN void
10508 nk_rp_setup_allow_out_of_mem(struct nk_rp_context *context, int allow_out_of_mem)
10509 {
10510  if (allow_out_of_mem)
10511  /* if it's ok to run out of memory, then don't bother aligning them; */
10512  /* this gives better packing, but may fail due to OOM (even though */
10513  /* the rectangles easily fit). @TODO a smarter approach would be to only */
10514  /* quantize once we've hit OOM, then we could get rid of this parameter. */
10515  context->align = 1;
10516  else {
10517  /* if it's not ok to run out of memory, then quantize the widths */
10518  /* so that num_nodes is always enough nodes. */
10519  /* */
10520  /* I.e. num_nodes * align >= width */
10521  /* align >= width / num_nodes */
10522  /* align = ceil(width/num_nodes) */
10523  context->align = (context->width + context->num_nodes-1) / context->num_nodes;
10524  }
10525 }
10526 NK_INTERN void
10527 nk_rp_init_target(struct nk_rp_context *context, int width, int height,
10528  struct nk_rp_node *nodes, int num_nodes)
10529 {
10530  int i;
10531 #ifndef STBRP_LARGE_RECTS
10532  NK_ASSERT(width <= 0xffff && height <= 0xffff);
10533 #endif
10534 
10535  for (i=0; i < num_nodes-1; ++i)
10536  nodes[i].next = &nodes[i+1];
10537  nodes[i].next = 0;
10538  context->init_mode = NK_RP__INIT_skyline;
10539  context->heuristic = NK_RP_HEURISTIC_Skyline_default;
10540  context->free_head = &nodes[0];
10541  context->active_head = &context->extra[0];
10542  context->width = width;
10543  context->height = height;
10544  context->num_nodes = num_nodes;
10545  nk_rp_setup_allow_out_of_mem(context, 0);
10546 
10547  /* node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) */
10548  context->extra[0].x = 0;
10549  context->extra[0].y = 0;
10550  context->extra[0].next = &context->extra[1];
10551  context->extra[1].x = (nk_rp_coord) width;
10552  context->extra[1].y = 65535;
10553  context->extra[1].next = 0;
10554 }
10555 /* find minimum y position if it starts at x1 */
10556 NK_INTERN int
10557 nk_rp__skyline_find_min_y(struct nk_rp_context *c, struct nk_rp_node *first,
10558  int x0, int width, int *pwaste)
10559 {
10560  struct nk_rp_node *node = first;
10561  int x1 = x0 + width;
10562  int min_y, visited_width, waste_area;
10563  NK_ASSERT(first->x <= x0);
10564  NK_UNUSED(c);
10565 
10566  NK_ASSERT(node->next->x > x0);
10567  /* we ended up handling this in the caller for efficiency */
10568  NK_ASSERT(node->x <= x0);
10569 
10570  min_y = 0;
10571  waste_area = 0;
10572  visited_width = 0;
10573  while (node->x < x1)
10574  {
10575  if (node->y > min_y) {
10576  /* raise min_y higher. */
10577  /* we've accounted for all waste up to min_y, */
10578  /* but we'll now add more waste for everything we've visited */
10579  waste_area += visited_width * (node->y - min_y);
10580  min_y = node->y;
10581  /* the first time through, visited_width might be reduced */
10582  if (node->x < x0)
10583  visited_width += node->next->x - x0;
10584  else
10585  visited_width += node->next->x - node->x;
10586  } else {
10587  /* add waste area */
10588  int under_width = node->next->x - node->x;
10589  if (under_width + visited_width > width)
10590  under_width = width - visited_width;
10591  waste_area += under_width * (min_y - node->y);
10592  visited_width += under_width;
10593  }
10594  node = node->next;
10595  }
10596  *pwaste = waste_area;
10597  return min_y;
10598 }
10599 NK_INTERN struct nk_rp__findresult
10600 nk_rp__skyline_find_best_pos(struct nk_rp_context *c, int width, int height)
10601 {
10602  int best_waste = (1<<30), best_x, best_y = (1 << 30);
10603  struct nk_rp__findresult fr;
10604  struct nk_rp_node **prev, *node, *tail, **best = 0;
10605 
10606  /* align to multiple of c->align */
10607  width = (width + c->align - 1);
10608  width -= width % c->align;
10609  NK_ASSERT(width % c->align == 0);
10610 
10611  node = c->active_head;
10612  prev = &c->active_head;
10613  while (node->x + width <= c->width) {
10614  int y,waste;
10615  y = nk_rp__skyline_find_min_y(c, node, node->x, width, &waste);
10616  /* actually just want to test BL */
10617  if (c->heuristic == NK_RP_HEURISTIC_Skyline_BL_sortHeight) {
10618  /* bottom left */
10619  if (y < best_y) {
10620  best_y = y;
10621  best = prev;
10622  }
10623  } else {
10624  /* best-fit */
10625  if (y + height <= c->height) {
10626  /* can only use it if it first vertically */
10627  if (y < best_y || (y == best_y && waste < best_waste)) {
10628  best_y = y;
10629  best_waste = waste;
10630  best = prev;
10631  }
10632  }
10633  }
10634  prev = &node->next;
10635  node = node->next;
10636  }
10637  best_x = (best == 0) ? 0 : (*best)->x;
10638 
10639  /* if doing best-fit (BF), we also have to try aligning right edge to each node position */
10640  /* */
10641  /* e.g, if fitting */
10642  /* */
10643  /* ____________________ */
10644  /* |____________________| */
10645  /* */
10646  /* into */
10647  /* */
10648  /* | | */
10649  /* | ____________| */
10650  /* |____________| */
10651  /* */
10652  /* then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned */
10653  /* */
10654  /* This makes BF take about 2x the time */
10655  if (c->heuristic == NK_RP_HEURISTIC_Skyline_BF_sortHeight)
10656  {
10657  tail = c->active_head;
10658  node = c->active_head;
10659  prev = &c->active_head;
10660  /* find first node that's admissible */
10661  while (tail->x < width)
10662  tail = tail->next;
10663  while (tail)
10664  {
10665  int xpos = tail->x - width;
10666  int y,waste;
10667  NK_ASSERT(xpos >= 0);
10668  /* find the left position that matches this */
10669  while (node->next->x <= xpos) {
10670  prev = &node->next;
10671  node = node->next;
10672  }
10673  NK_ASSERT(node->next->x > xpos && node->x <= xpos);
10674  y = nk_rp__skyline_find_min_y(c, node, xpos, width, &waste);
10675  if (y + height < c->height) {
10676  if (y <= best_y) {
10677  if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
10678  best_x = xpos;
10679  NK_ASSERT(y <= best_y);
10680  best_y = y;
10681  best_waste = waste;
10682  best = prev;
10683  }
10684  }
10685  }
10686  tail = tail->next;
10687  }
10688  }
10689  fr.prev_link = best;
10690  fr.x = best_x;
10691  fr.y = best_y;
10692  return fr;
10693 }
10694 NK_INTERN struct nk_rp__findresult
10695 nk_rp__skyline_pack_rectangle(struct nk_rp_context *context, int width, int height)
10696 {
10697  /* find best position according to heuristic */
10698  struct nk_rp__findresult res = nk_rp__skyline_find_best_pos(context, width, height);
10699  struct nk_rp_node *node, *cur;
10700 
10701  /* bail if: */
10702  /* 1. it failed */
10703  /* 2. the best node doesn't fit (we don't always check this) */
10704  /* 3. we're out of memory */
10705  if (res.prev_link == 0 || res.y + height > context->height || context->free_head == 0) {
10706  res.prev_link = 0;
10707  return res;
10708  }
10709 
10710  /* on success, create new node */
10711  node = context->free_head;
10712  node->x = (nk_rp_coord) res.x;
10713  node->y = (nk_rp_coord) (res.y + height);
10714 
10715  context->free_head = node->next;
10716 
10717  /* insert the new node into the right starting point, and */
10718  /* let 'cur' point to the remaining nodes needing to be */
10719  /* stitched back in */
10720  cur = *res.prev_link;
10721  if (cur->x < res.x) {
10722  /* preserve the existing one, so start testing with the next one */
10723  struct nk_rp_node *next = cur->next;
10724  cur->next = node;
10725  cur = next;
10726  } else {
10727  *res.prev_link = node;
10728  }
10729 
10730  /* from here, traverse cur and free the nodes, until we get to one */
10731  /* that shouldn't be freed */
10732  while (cur->next && cur->next->x <= res.x + width) {
10733  struct nk_rp_node *next = cur->next;
10734  /* move the current node to the free list */
10735  cur->next = context->free_head;
10736  context->free_head = cur;
10737  cur = next;
10738  }
10739  /* stitch the list back in */
10740  node->next = cur;
10741 
10742  if (cur->x < res.x + width)
10743  cur->x = (nk_rp_coord) (res.x + width);
10744  return res;
10745 }
10746 NK_INTERN int
10747 nk_rect_height_compare(const void *a, const void *b)
10748 {
10749  const struct nk_rp_rect *p = (const struct nk_rp_rect *) a;
10750  const struct nk_rp_rect *q = (const struct nk_rp_rect *) b;
10751  if (p->h > q->h)
10752  return -1;
10753  if (p->h < q->h)
10754  return 1;
10755  return (p->w > q->w) ? -1 : (p->w < q->w);
10756 }
10757 NK_INTERN int
10758 nk_rect_original_order(const void *a, const void *b)
10759 {
10760  const struct nk_rp_rect *p = (const struct nk_rp_rect *) a;
10761  const struct nk_rp_rect *q = (const struct nk_rp_rect *) b;
10762  return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
10763 }
10764 NK_INTERN void
10765 nk_rp_qsort(struct nk_rp_rect *array, unsigned int len, int(*cmp)(const void*,const void*))
10766 {
10767  /* iterative quick sort */
10768  #define NK_MAX_SORT_STACK 64
10769  unsigned right, left = 0, stack[NK_MAX_SORT_STACK], pos = 0;
10770  unsigned seed = len/2 * 69069+1;
10771  for (;;) {
10772  for (; left+1 < len; len++) {
10773  struct nk_rp_rect pivot, tmp;
10774  if (pos == NK_MAX_SORT_STACK) len = stack[pos = 0];
10775  pivot = array[left+seed%(len-left)];
10776  seed = seed * 69069 + 1;
10777  stack[pos++] = len;
10778  for (right = left-1;;) {
10779  while (cmp(&array[++right], &pivot) < 0);
10780  while (cmp(&pivot, &array[--len]) < 0);
10781  if (right >= len) break;
10782  tmp = array[right];
10783  array[right] = array[len];
10784  array[len] = tmp;
10785  }
10786  }
10787  if (pos == 0) break;
10788  left = len;
10789  len = stack[--pos];
10790  }
10791  #undef NK_MAX_SORT_STACK
10792 }
10793 NK_INTERN void
10794 nk_rp_pack_rects(struct nk_rp_context *context, struct nk_rp_rect *rects, int num_rects)
10795 {
10796  int i;
10797  /* we use the 'was_packed' field internally to allow sorting/unsorting */
10798  for (i=0; i < num_rects; ++i) {
10799  rects[i].was_packed = i;
10800  }
10801 
10802  /* sort according to heuristic */
10803  nk_rp_qsort(rects, (unsigned)num_rects, nk_rect_height_compare);
10804 
10805  for (i=0; i < num_rects; ++i) {
10806  struct nk_rp__findresult fr = nk_rp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
10807  if (fr.prev_link) {
10808  rects[i].x = (nk_rp_coord) fr.x;
10809  rects[i].y = (nk_rp_coord) fr.y;
10810  } else {
10811  rects[i].x = rects[i].y = NK_RP__MAXVAL;
10812  }
10813  }
10814 
10815  /* unsort */
10816  nk_rp_qsort(rects, (unsigned)num_rects, nk_rect_original_order);
10817 
10818  /* set was_packed flags */
10819  for (i=0; i < num_rects; ++i)
10820  rects[i].was_packed = !(rects[i].x == NK_RP__MAXVAL && rects[i].y == NK_RP__MAXVAL);
10821 }
10822 
10823 /*
10824  * ==============================================================
10825  *
10826  * TRUETYPE
10827  *
10828  * ===============================================================
10829  */
10830 /* stb_truetype.h - v1.07 - public domain */
10831 #define NK_TT_MAX_OVERSAMPLE 8
10832 #define NK_TT__OVER_MASK (NK_TT_MAX_OVERSAMPLE-1)
10833 
10834 struct nk_tt_bakedchar {
10835  unsigned short x0,y0,x1,y1;
10836  /* coordinates of bbox in bitmap */
10837  float xoff,yoff,xadvance;
10838 };
10839 
10840 struct nk_tt_aligned_quad{
10841  float x0,y0,s0,t0; /* top-left */
10842  float x1,y1,s1,t1; /* bottom-right */
10843 };
10844 
10845 struct nk_tt_packedchar {
10846  unsigned short x0,y0,x1,y1;
10847  /* coordinates of bbox in bitmap */
10848  float xoff,yoff,xadvance;
10849  float xoff2,yoff2;
10850 };
10851 
10852 struct nk_tt_pack_range {
10853  float font_size;
10854  int first_unicode_codepoint_in_range;
10855  /* if non-zero, then the chars are continuous, and this is the first codepoint */
10856  int *array_of_unicode_codepoints;
10857  /* if non-zero, then this is an array of unicode codepoints */
10858  int num_chars;
10859  struct nk_tt_packedchar *chardata_for_range; /* output */
10860  unsigned char h_oversample, v_oversample;
10861  /* don't set these, they're used internally */
10862 };
10863 
10864 struct nk_tt_pack_context {
10865  void *pack_info;
10866  int width;
10867  int height;
10868  int stride_in_bytes;
10869  int padding;
10870  unsigned int h_oversample, v_oversample;
10871  unsigned char *pixels;
10872  void *nodes;
10873 };
10874 
10875 struct nk_tt_fontinfo {
10876  const unsigned char* data; /* pointer to .ttf file */
10877  int fontstart;/* offset of start of font */
10878  int numGlyphs;/* number of glyphs, needed for range checking */
10879  int loca,head,glyf,hhea,hmtx,kern; /* table locations as offset from start of .ttf */
10880  int index_map; /* a cmap mapping for our chosen character encoding */
10881  int indexToLocFormat; /* format needed to map from glyph index to glyph */
10882 };
10883 
10884 enum {
10885  NK_TT_vmove=1,
10886  NK_TT_vline,
10887  NK_TT_vcurve
10888 };
10889 
10890 struct nk_tt_vertex {
10891  short x,y,cx,cy;
10892  unsigned char type,padding;
10893 };
10894 
10895 struct nk_tt__bitmap{
10896  int w,h,stride;
10897  unsigned char *pixels;
10898 };
10899 
10900 struct nk_tt__hheap_chunk {
10901  struct nk_tt__hheap_chunk *next;
10902 };
10903 struct nk_tt__hheap {
10904  struct nk_allocator alloc;
10905  struct nk_tt__hheap_chunk *head;
10906  void *first_free;
10907  int num_remaining_in_head_chunk;
10908 };
10909 
10910 struct nk_tt__edge {
10911  float x0,y0, x1,y1;
10912  int invert;
10913 };
10914 
10915 struct nk_tt__active_edge {
10916  struct nk_tt__active_edge *next;
10917  float fx,fdx,fdy;
10918  float direction;
10919  float sy;
10920  float ey;
10921 };
10922 struct nk_tt__point {float x,y;};
10923 
10924 #define NK_TT_MACSTYLE_DONTCARE 0
10925 #define NK_TT_MACSTYLE_BOLD 1
10926 #define NK_TT_MACSTYLE_ITALIC 2
10927 #define NK_TT_MACSTYLE_UNDERSCORE 4
10928 #define NK_TT_MACSTYLE_NONE 8
10929 /* <= not same as 0, this makes us check the bitfield is 0 */
10930 
10931 enum { /* platformID */
10932  NK_TT_PLATFORM_ID_UNICODE =0,
10933  NK_TT_PLATFORM_ID_MAC =1,
10934  NK_TT_PLATFORM_ID_ISO =2,
10935  NK_TT_PLATFORM_ID_MICROSOFT =3
10936 };
10937 
10938 enum { /* encodingID for NK_TT_PLATFORM_ID_UNICODE */
10939  NK_TT_UNICODE_EID_UNICODE_1_0 =0,
10940  NK_TT_UNICODE_EID_UNICODE_1_1 =1,
10941  NK_TT_UNICODE_EID_ISO_10646 =2,
10942  NK_TT_UNICODE_EID_UNICODE_2_0_BMP=3,
10943  NK_TT_UNICODE_EID_UNICODE_2_0_FULL=4
10944 };
10945 
10946 enum { /* encodingID for NK_TT_PLATFORM_ID_MICROSOFT */
10947  NK_TT_MS_EID_SYMBOL =0,
10948  NK_TT_MS_EID_UNICODE_BMP =1,
10949  NK_TT_MS_EID_SHIFTJIS =2,
10950  NK_TT_MS_EID_UNICODE_FULL =10
10951 };
10952 
10953 enum { /* encodingID for NK_TT_PLATFORM_ID_MAC; same as Script Manager codes */
10954  NK_TT_MAC_EID_ROMAN =0, NK_TT_MAC_EID_ARABIC =4,
10955  NK_TT_MAC_EID_JAPANESE =1, NK_TT_MAC_EID_HEBREW =5,
10956  NK_TT_MAC_EID_CHINESE_TRAD =2, NK_TT_MAC_EID_GREEK =6,
10957  NK_TT_MAC_EID_KOREAN =3, NK_TT_MAC_EID_RUSSIAN =7
10958 };
10959 
10960 enum { /* languageID for NK_TT_PLATFORM_ID_MICROSOFT; same as LCID... */
10961  /* problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs */
10962  NK_TT_MS_LANG_ENGLISH =0x0409, NK_TT_MS_LANG_ITALIAN =0x0410,
10963  NK_TT_MS_LANG_CHINESE =0x0804, NK_TT_MS_LANG_JAPANESE =0x0411,
10964  NK_TT_MS_LANG_DUTCH =0x0413, NK_TT_MS_LANG_KOREAN =0x0412,
10965  NK_TT_MS_LANG_FRENCH =0x040c, NK_TT_MS_LANG_RUSSIAN =0x0419,
10966  NK_TT_MS_LANG_GERMAN =0x0407, NK_TT_MS_LANG_SPANISH =0x0409,
10967  NK_TT_MS_LANG_HEBREW =0x040d, NK_TT_MS_LANG_SWEDISH =0x041D
10968 };
10969 
10970 enum { /* languageID for NK_TT_PLATFORM_ID_MAC */
10971  NK_TT_MAC_LANG_ENGLISH =0 , NK_TT_MAC_LANG_JAPANESE =11,
10972  NK_TT_MAC_LANG_ARABIC =12, NK_TT_MAC_LANG_KOREAN =23,
10973  NK_TT_MAC_LANG_DUTCH =4 , NK_TT_MAC_LANG_RUSSIAN =32,
10974  NK_TT_MAC_LANG_FRENCH =1 , NK_TT_MAC_LANG_SPANISH =6 ,
10975  NK_TT_MAC_LANG_GERMAN =2 , NK_TT_MAC_LANG_SWEDISH =5 ,
10976  NK_TT_MAC_LANG_HEBREW =10, NK_TT_MAC_LANG_CHINESE_SIMPLIFIED =33,
10977  NK_TT_MAC_LANG_ITALIAN =3 , NK_TT_MAC_LANG_CHINESE_TRAD =19
10978 };
10979 
10980 #define nk_ttBYTE(p) (* (const nk_byte *) (p))
10981 #define nk_ttCHAR(p) (* (const char *) (p))
10982 
10983 #if defined(NK_BIGENDIAN) && !defined(NK_ALLOW_UNALIGNED_TRUETYPE)
10984  #define nk_ttUSHORT(p) (* (nk_ushort *) (p))
10985  #define nk_ttSHORT(p) (* (nk_short *) (p))
10986  #define nk_ttULONG(p) (* (nk_uint *) (p))
10987  #define nk_ttLONG(p) (* (nk_int *) (p))
10988 #else
10989  static nk_ushort nk_ttUSHORT(const nk_byte *p) { return (nk_ushort)(p[0]*256 + p[1]); }
10990  static nk_short nk_ttSHORT(const nk_byte *p) { return (nk_short)(p[0]*256 + p[1]); }
10991  static nk_uint nk_ttULONG(const nk_byte *p) { return (nk_uint)((p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]); }
10992 #endif
10993 
10994 #define nk_tt_tag4(p,c0,c1,c2,c3)\
10995  ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
10996 #define nk_tt_tag(p,str) nk_tt_tag4(p,str[0],str[1],str[2],str[3])
10997 
10998 NK_INTERN int nk_tt_GetGlyphShape(const struct nk_tt_fontinfo *info, struct nk_allocator *alloc,
10999  int glyph_index, struct nk_tt_vertex **pvertices);
11000 
11002 nk_tt__find_table(const nk_byte *data, nk_uint fontstart, const char *tag)
11003 {
11004  /* @OPTIMIZE: binary search */
11005  nk_int num_tables = nk_ttUSHORT(data+fontstart+4);
11006  nk_uint tabledir = fontstart + 12;
11007  nk_int i;
11008  for (i = 0; i < num_tables; ++i) {
11009  nk_uint loc = tabledir + (nk_uint)(16*i);
11010  if (nk_tt_tag(data+loc+0, tag))
11011  return nk_ttULONG(data+loc+8);
11012  }
11013  return 0;
11014 }
11015 NK_INTERN int
11016 nk_tt_InitFont(struct nk_tt_fontinfo *info, const unsigned char *data2, int fontstart)
11017 {
11018  nk_uint cmap, t;
11019  nk_int i,numTables;
11020  const nk_byte *data = (const nk_byte *) data2;
11021 
11022  info->data = data;
11023  info->fontstart = fontstart;
11024 
11025  cmap = nk_tt__find_table(data, (nk_uint)fontstart, "cmap"); /* required */
11026  info->loca = (int)nk_tt__find_table(data, (nk_uint)fontstart, "loca"); /* required */
11027  info->head = (int)nk_tt__find_table(data, (nk_uint)fontstart, "head"); /* required */
11028  info->glyf = (int)nk_tt__find_table(data, (nk_uint)fontstart, "glyf"); /* required */
11029  info->hhea = (int)nk_tt__find_table(data, (nk_uint)fontstart, "hhea"); /* required */
11030  info->hmtx = (int)nk_tt__find_table(data, (nk_uint)fontstart, "hmtx"); /* required */
11031  info->kern = (int)nk_tt__find_table(data, (nk_uint)fontstart, "kern"); /* not required */
11032  if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx)
11033  return 0;
11034 
11035  t = nk_tt__find_table(data, (nk_uint)fontstart, "maxp");
11036  if (t) info->numGlyphs = nk_ttUSHORT(data+t+4);
11037  else info->numGlyphs = 0xffff;
11038 
11039  /* find a cmap encoding table we understand *now* to avoid searching */
11040  /* later. (todo: could make this installable) */
11041  /* the same regardless of glyph. */
11042  numTables = nk_ttUSHORT(data + cmap + 2);
11043  info->index_map = 0;
11044  for (i=0; i < numTables; ++i)
11045  {
11046  nk_uint encoding_record = cmap + 4 + 8 * (nk_uint)i;
11047  /* find an encoding we understand: */
11048  switch(nk_ttUSHORT(data+encoding_record)) {
11049  case NK_TT_PLATFORM_ID_MICROSOFT:
11050  switch (nk_ttUSHORT(data+encoding_record+2)) {
11051  case NK_TT_MS_EID_UNICODE_BMP:
11052  case NK_TT_MS_EID_UNICODE_FULL:
11053  /* MS/Unicode */
11054  info->index_map = (int)(cmap + nk_ttULONG(data+encoding_record+4));
11055  break;
11056  default: break;
11057  } break;
11058  case NK_TT_PLATFORM_ID_UNICODE:
11059  /* Mac/iOS has these */
11060  /* all the encodingIDs are unicode, so we don't bother to check it */
11061  info->index_map = (int)(cmap + nk_ttULONG(data+encoding_record+4));
11062  break;
11063  default: break;
11064  }
11065  }
11066  if (info->index_map == 0)
11067  return 0;
11068  info->indexToLocFormat = nk_ttUSHORT(data+info->head + 50);
11069  return 1;
11070 }
11071 NK_INTERN int
11072 nk_tt_FindGlyphIndex(const struct nk_tt_fontinfo *info, int unicode_codepoint)
11073 {
11074  const nk_byte *data = info->data;
11075  nk_uint index_map = (nk_uint)info->index_map;
11076 
11077  nk_ushort format = nk_ttUSHORT(data + index_map + 0);
11078  if (format == 0) { /* apple byte encoding */
11079  nk_int bytes = nk_ttUSHORT(data + index_map + 2);
11080  if (unicode_codepoint < bytes-6)
11081  return nk_ttBYTE(data + index_map + 6 + unicode_codepoint);
11082  return 0;
11083  } else if (format == 6) {
11084  nk_uint first = nk_ttUSHORT(data + index_map + 6);
11085  nk_uint count = nk_ttUSHORT(data + index_map + 8);
11086  if ((nk_uint) unicode_codepoint >= first && (nk_uint) unicode_codepoint < first+count)
11087  return nk_ttUSHORT(data + index_map + 10 + (unicode_codepoint - (int)first)*2);
11088  return 0;
11089  } else if (format == 2) {
11090  NK_ASSERT(0); /* @TODO: high-byte mapping for japanese/chinese/korean */
11091  return 0;
11092  } else if (format == 4) { /* standard mapping for windows fonts: binary search collection of ranges */
11093  nk_ushort segcount = nk_ttUSHORT(data+index_map+6) >> 1;
11094  nk_ushort searchRange = nk_ttUSHORT(data+index_map+8) >> 1;
11095  nk_ushort entrySelector = nk_ttUSHORT(data+index_map+10);
11096  nk_ushort rangeShift = nk_ttUSHORT(data+index_map+12) >> 1;
11097 
11098  /* do a binary search of the segments */
11099  nk_uint endCount = index_map + 14;
11100  nk_uint search = endCount;
11101 
11102  if (unicode_codepoint > 0xffff)
11103  return 0;
11104 
11105  /* they lie from endCount .. endCount + segCount */
11106  /* but searchRange is the nearest power of two, so... */
11107  if (unicode_codepoint >= nk_ttUSHORT(data + search + rangeShift*2))
11108  search += (nk_uint)(rangeShift*2);
11109 
11110  /* now decrement to bias correctly to find smallest */
11111  search -= 2;
11112  while (entrySelector) {
11113  nk_ushort end;
11114  searchRange >>= 1;
11115  end = nk_ttUSHORT(data + search + searchRange*2);
11116  if (unicode_codepoint > end)
11117  search += (nk_uint)(searchRange*2);
11118  --entrySelector;
11119  }
11120  search += 2;
11121 
11122  {
11123  nk_ushort offset, start;
11124  nk_ushort item = (nk_ushort) ((search - endCount) >> 1);
11125 
11126  NK_ASSERT(unicode_codepoint <= nk_ttUSHORT(data + endCount + 2*item));
11127  start = nk_ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
11128  if (unicode_codepoint < start)
11129  return 0;
11130 
11131  offset = nk_ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
11132  if (offset == 0)
11133  return (nk_ushort) (unicode_codepoint + nk_ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));
11134 
11135  return nk_ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
11136  }
11137  } else if (format == 12 || format == 13) {
11138  nk_uint ngroups = nk_ttULONG(data+index_map+12);
11139  nk_int low,high;
11140  low = 0; high = (nk_int)ngroups;
11141  /* Binary search the right group. */
11142  while (low < high) {
11143  nk_int mid = low + ((high-low) >> 1); /* rounds down, so low <= mid < high */
11144  nk_uint start_char = nk_ttULONG(data+index_map+16+mid*12);
11145  nk_uint end_char = nk_ttULONG(data+index_map+16+mid*12+4);
11146  if ((nk_uint) unicode_codepoint < start_char)
11147  high = mid;
11148  else if ((nk_uint) unicode_codepoint > end_char)
11149  low = mid+1;
11150  else {
11151  nk_uint start_glyph = nk_ttULONG(data+index_map+16+mid*12+8);
11152  if (format == 12)
11153  return (int)start_glyph + (int)unicode_codepoint - (int)start_char;
11154  else /* format == 13 */
11155  return (int)start_glyph;
11156  }
11157  }
11158  return 0; /* not found */
11159  }
11160  /* @TODO */
11161  NK_ASSERT(0);
11162  return 0;
11163 }
11164 NK_INTERN void
11165 nk_tt_setvertex(struct nk_tt_vertex *v, nk_byte type, nk_int x, nk_int y, nk_int cx, nk_int cy)
11166 {
11167  v->type = type;
11168  v->x = (nk_short) x;
11169  v->y = (nk_short) y;
11170  v->cx = (nk_short) cx;
11171  v->cy = (nk_short) cy;
11172 }
11173 NK_INTERN int
11174 nk_tt__GetGlyfOffset(const struct nk_tt_fontinfo *info, int glyph_index)
11175 {
11176  int g1,g2;
11177  if (glyph_index >= info->numGlyphs) return -1; /* glyph index out of range */
11178  if (info->indexToLocFormat >= 2) return -1; /* unknown index->glyph map format */
11179 
11180  if (info->indexToLocFormat == 0) {
11181  g1 = info->glyf + nk_ttUSHORT(info->data + info->loca + glyph_index * 2) * 2;
11182  g2 = info->glyf + nk_ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2;
11183  } else {
11184  g1 = info->glyf + (int)nk_ttULONG (info->data + info->loca + glyph_index * 4);
11185  g2 = info->glyf + (int)nk_ttULONG (info->data + info->loca + glyph_index * 4 + 4);
11186  }
11187  return g1==g2 ? -1 : g1; /* if length is 0, return -1 */
11188 }
11189 NK_INTERN int
11190 nk_tt_GetGlyphBox(const struct nk_tt_fontinfo *info, int glyph_index,
11191  int *x0, int *y0, int *x1, int *y1)
11192 {
11193  int g = nk_tt__GetGlyfOffset(info, glyph_index);
11194  if (g < 0) return 0;
11195 
11196  if (x0) *x0 = nk_ttSHORT(info->data + g + 2);
11197  if (y0) *y0 = nk_ttSHORT(info->data + g + 4);
11198  if (x1) *x1 = nk_ttSHORT(info->data + g + 6);
11199  if (y1) *y1 = nk_ttSHORT(info->data + g + 8);
11200  return 1;
11201 }
11202 NK_INTERN int
11203 nk_tt__close_shape(struct nk_tt_vertex *vertices, int num_vertices, int was_off,
11204  int start_off, nk_int sx, nk_int sy, nk_int scx, nk_int scy, nk_int cx, nk_int cy)
11205 {
11206  if (start_off) {
11207  if (was_off)
11208  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);
11209  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, sx,sy,scx,scy);
11210  } else {
11211  if (was_off)
11212  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve,sx,sy,cx,cy);
11213  else
11214  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vline,sx,sy,0,0);
11215  }
11216  return num_vertices;
11217 }
11218 NK_INTERN int
11219 nk_tt_GetGlyphShape(const struct nk_tt_fontinfo *info, struct nk_allocator *alloc,
11220  int glyph_index, struct nk_tt_vertex **pvertices)
11221 {
11222  nk_short numberOfContours;
11223  const nk_byte *endPtsOfContours;
11224  const nk_byte *data = info->data;
11225  struct nk_tt_vertex *vertices=0;
11226  int num_vertices=0;
11227  int g = nk_tt__GetGlyfOffset(info, glyph_index);
11228  *pvertices = 0;
11229 
11230  if (g < 0) return 0;
11231  numberOfContours = nk_ttSHORT(data + g);
11232  if (numberOfContours > 0) {
11233  nk_byte flags=0,flagcount;
11234  nk_int ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0;
11235  nk_int x,y,cx,cy,sx,sy, scx,scy;
11236  const nk_byte *points;
11237  endPtsOfContours = (data + g + 10);
11238  ins = nk_ttUSHORT(data + g + 10 + numberOfContours * 2);
11239  points = data + g + 10 + numberOfContours * 2 + 2 + ins;
11240 
11241  n = 1+nk_ttUSHORT(endPtsOfContours + numberOfContours*2-2);
11242  m = n + 2*numberOfContours; /* a loose bound on how many vertices we might need */
11243  vertices = (struct nk_tt_vertex *)alloc->alloc(alloc->userdata, 0, (nk_size)m * sizeof(vertices[0]));
11244  if (vertices == 0)
11245  return 0;
11246 
11247  next_move = 0;
11248  flagcount=0;
11249 
11250  /* in first pass, we load uninterpreted data into the allocated array */
11251  /* above, shifted to the end of the array so we won't overwrite it when */
11252  /* we create our final data starting from the front */
11253  off = m - n; /* starting offset for uninterpreted data, regardless of how m ends up being calculated */
11254 
11255  /* first load flags */
11256  for (i=0; i < n; ++i) {
11257  if (flagcount == 0) {
11258  flags = *points++;
11259  if (flags & 8)
11260  flagcount = *points++;
11261  } else --flagcount;
11262  vertices[off+i].type = flags;
11263  }
11264 
11265  /* now load x coordinates */
11266  x=0;
11267  for (i=0; i < n; ++i) {
11268  flags = vertices[off+i].type;
11269  if (flags & 2) {
11270  nk_short dx = *points++;
11271  x += (flags & 16) ? dx : -dx; /* ??? */
11272  } else {
11273  if (!(flags & 16)) {
11274  x = x + (nk_short) (points[0]*256 + points[1]);
11275  points += 2;
11276  }
11277  }
11278  vertices[off+i].x = (nk_short) x;
11279  }
11280 
11281  /* now load y coordinates */
11282  y=0;
11283  for (i=0; i < n; ++i) {
11284  flags = vertices[off+i].type;
11285  if (flags & 4) {
11286  nk_short dy = *points++;
11287  y += (flags & 32) ? dy : -dy; /* ??? */
11288  } else {
11289  if (!(flags & 32)) {
11290  y = y + (nk_short) (points[0]*256 + points[1]);
11291  points += 2;
11292  }
11293  }
11294  vertices[off+i].y = (nk_short) y;
11295  }
11296 
11297  /* now convert them to our format */
11298  num_vertices=0;
11299  sx = sy = cx = cy = scx = scy = 0;
11300  for (i=0; i < n; ++i)
11301  {
11302  flags = vertices[off+i].type;
11303  x = (nk_short) vertices[off+i].x;
11304  y = (nk_short) vertices[off+i].y;
11305 
11306  if (next_move == i) {
11307  if (i != 0)
11308  num_vertices = nk_tt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
11309 
11310  /* now start the new one */
11311  start_off = !(flags & 1);
11312  if (start_off) {
11313  /* if we start off with an off-curve point, then when we need to find a point on the curve */
11314  /* where we can start, and we need to save some state for when we wraparound. */
11315  scx = x;
11316  scy = y;
11317  if (!(vertices[off+i+1].type & 1)) {
11318  /* next point is also a curve point, so interpolate an on-point curve */
11319  sx = (x + (nk_int) vertices[off+i+1].x) >> 1;
11320  sy = (y + (nk_int) vertices[off+i+1].y) >> 1;
11321  } else {
11322  /* otherwise just use the next point as our start point */
11323  sx = (nk_int) vertices[off+i+1].x;
11324  sy = (nk_int) vertices[off+i+1].y;
11325  ++i; /* we're using point i+1 as the starting point, so skip it */
11326  }
11327  } else {
11328  sx = x;
11329  sy = y;
11330  }
11331  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vmove,sx,sy,0,0);
11332  was_off = 0;
11333  next_move = 1 + nk_ttUSHORT(endPtsOfContours+j*2);
11334  ++j;
11335  } else {
11336  if (!(flags & 1))
11337  { /* if it's a curve */
11338  if (was_off) /* two off-curve control points in a row means interpolate an on-curve midpoint */
11339  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);
11340  cx = x;
11341  cy = y;
11342  was_off = 1;
11343  } else {
11344  if (was_off)
11345  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, x,y, cx, cy);
11346  else nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vline, x,y,0,0);
11347  was_off = 0;
11348  }
11349  }
11350  }
11351  num_vertices = nk_tt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
11352  } else if (numberOfContours == -1) {
11353  /* Compound shapes. */
11354  int more = 1;
11355  const nk_byte *comp = data + g + 10;
11356  num_vertices = 0;
11357  vertices = 0;
11358 
11359  while (more)
11360  {
11361  nk_ushort flags, gidx;
11362  int comp_num_verts = 0, i;
11363  struct nk_tt_vertex *comp_verts = 0, *tmp = 0;
11364  float mtx[6] = {1,0,0,1,0,0}, m, n;
11365 
11366  flags = (nk_ushort)nk_ttSHORT(comp); comp+=2;
11367  gidx = (nk_ushort)nk_ttSHORT(comp); comp+=2;
11368 
11369  if (flags & 2) { /* XY values */
11370  if (flags & 1) { /* shorts */
11371  mtx[4] = nk_ttSHORT(comp); comp+=2;
11372  mtx[5] = nk_ttSHORT(comp); comp+=2;
11373  } else {
11374  mtx[4] = nk_ttCHAR(comp); comp+=1;
11375  mtx[5] = nk_ttCHAR(comp); comp+=1;
11376  }
11377  } else {
11378  /* @TODO handle matching point */
11379  NK_ASSERT(0);
11380  }
11381  if (flags & (1<<3)) { /* WE_HAVE_A_SCALE */
11382  mtx[0] = mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2;
11383  mtx[1] = mtx[2] = 0;
11384  } else if (flags & (1<<6)) { /* WE_HAVE_AN_X_AND_YSCALE */
11385  mtx[0] = nk_ttSHORT(comp)/16384.0f; comp+=2;
11386  mtx[1] = mtx[2] = 0;
11387  mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2;
11388  } else if (flags & (1<<7)) { /* WE_HAVE_A_TWO_BY_TWO */
11389  mtx[0] = nk_ttSHORT(comp)/16384.0f; comp+=2;
11390  mtx[1] = nk_ttSHORT(comp)/16384.0f; comp+=2;
11391  mtx[2] = nk_ttSHORT(comp)/16384.0f; comp+=2;
11392  mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2;
11393  }
11394 
11395  /* Find transformation scales. */
11396  m = (float) NK_SQRT(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
11397  n = (float) NK_SQRT(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
11398 
11399  /* Get indexed glyph. */
11400  comp_num_verts = nk_tt_GetGlyphShape(info, alloc, gidx, &comp_verts);
11401  if (comp_num_verts > 0)
11402  {
11403  /* Transform vertices. */
11404  for (i = 0; i < comp_num_verts; ++i) {
11405  struct nk_tt_vertex* v = &comp_verts[i];
11406  short x,y;
11407  x=v->x; y=v->y;
11408  v->x = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
11409  v->y = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
11410  x=v->cx; y=v->cy;
11411  v->cx = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
11412  v->cy = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
11413  }
11414  /* Append vertices. */
11415  tmp = (struct nk_tt_vertex*)alloc->alloc(alloc->userdata, 0,
11416  (nk_size)(num_vertices+comp_num_verts)*sizeof(struct nk_tt_vertex));
11417  if (!tmp) {
11418  if (vertices) alloc->free(alloc->userdata, vertices);
11419  if (comp_verts) alloc->free(alloc->userdata, comp_verts);
11420  return 0;
11421  }
11422  if (num_vertices > 0) NK_MEMCPY(tmp, vertices, (nk_size)num_vertices*sizeof(struct nk_tt_vertex));
11423  NK_MEMCPY(tmp+num_vertices, comp_verts, (nk_size)comp_num_verts*sizeof(struct nk_tt_vertex));
11424  if (vertices) alloc->free(alloc->userdata,vertices);
11425  vertices = tmp;
11426  alloc->free(alloc->userdata,comp_verts);
11427  num_vertices += comp_num_verts;
11428  }
11429  /* More components ? */
11430  more = flags & (1<<5);
11431  }
11432  } else if (numberOfContours < 0) {
11433  /* @TODO other compound variations? */
11434  NK_ASSERT(0);
11435  } else {
11436  /* numberOfCounters == 0, do nothing */
11437  }
11438  *pvertices = vertices;
11439  return num_vertices;
11440 }
11441 NK_INTERN void
11442 nk_tt_GetGlyphHMetrics(const struct nk_tt_fontinfo *info, int glyph_index,
11443  int *advanceWidth, int *leftSideBearing)
11444 {
11445  nk_ushort numOfLongHorMetrics = nk_ttUSHORT(info->data+info->hhea + 34);
11446  if (glyph_index < numOfLongHorMetrics) {
11447  if (advanceWidth)
11448  *advanceWidth = nk_ttSHORT(info->data + info->hmtx + 4*glyph_index);
11449  if (leftSideBearing)
11450  *leftSideBearing = nk_ttSHORT(info->data + info->hmtx + 4*glyph_index + 2);
11451  } else {
11452  if (advanceWidth)
11453  *advanceWidth = nk_ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1));
11454  if (leftSideBearing)
11455  *leftSideBearing = nk_ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));
11456  }
11457 }
11458 NK_INTERN void
11459 nk_tt_GetFontVMetrics(const struct nk_tt_fontinfo *info,
11460  int *ascent, int *descent, int *lineGap)
11461 {
11462  if (ascent ) *ascent = nk_ttSHORT(info->data+info->hhea + 4);
11463  if (descent) *descent = nk_ttSHORT(info->data+info->hhea + 6);
11464  if (lineGap) *lineGap = nk_ttSHORT(info->data+info->hhea + 8);
11465 }
11466 NK_INTERN float
11467 nk_tt_ScaleForPixelHeight(const struct nk_tt_fontinfo *info, float height)
11468 {
11469  int fheight = nk_ttSHORT(info->data + info->hhea + 4) - nk_ttSHORT(info->data + info->hhea + 6);
11470  return (float) height / (float)fheight;
11471 }
11472 NK_INTERN float
11473 nk_tt_ScaleForMappingEmToPixels(const struct nk_tt_fontinfo *info, float pixels)
11474 {
11475  int unitsPerEm = nk_ttUSHORT(info->data + info->head + 18);
11476  return pixels / (float)unitsPerEm;
11477 }
11478 
11479 /*-------------------------------------------------------------
11480  * antialiasing software rasterizer
11481  * --------------------------------------------------------------*/
11482 NK_INTERN void
11483 nk_tt_GetGlyphBitmapBoxSubpixel(const struct nk_tt_fontinfo *font,
11484  int glyph, float scale_x, float scale_y,float shift_x, float shift_y,
11485  int *ix0, int *iy0, int *ix1, int *iy1)
11486 {
11487  int x0,y0,x1,y1;
11488  if (!nk_tt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) {
11489  /* e.g. space character */
11490  if (ix0) *ix0 = 0;
11491  if (iy0) *iy0 = 0;
11492  if (ix1) *ix1 = 0;
11493  if (iy1) *iy1 = 0;
11494  } else {
11495  /* move to integral bboxes (treating pixels as little squares, what pixels get touched)? */
11496  if (ix0) *ix0 = nk_ifloorf((float)x0 * scale_x + shift_x);
11497  if (iy0) *iy0 = nk_ifloorf((float)-y1 * scale_y + shift_y);
11498  if (ix1) *ix1 = nk_iceilf ((float)x1 * scale_x + shift_x);
11499  if (iy1) *iy1 = nk_iceilf ((float)-y0 * scale_y + shift_y);
11500  }
11501 }
11502 NK_INTERN void
11503 nk_tt_GetGlyphBitmapBox(const struct nk_tt_fontinfo *font, int glyph,
11504  float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
11505 {
11506  nk_tt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1);
11507 }
11508 
11509 /*-------------------------------------------------------------
11510  * Rasterizer
11511  * --------------------------------------------------------------*/
11512 NK_INTERN void*
11513 nk_tt__hheap_alloc(struct nk_tt__hheap *hh, nk_size size)
11514 {
11515  if (hh->first_free) {
11516  void *p = hh->first_free;
11517  hh->first_free = * (void **) p;
11518  return p;
11519  } else {
11520  if (hh->num_remaining_in_head_chunk == 0) {
11521  int count = (size < 32 ? 2000 : size < 128 ? 800 : 100);
11522  struct nk_tt__hheap_chunk *c = (struct nk_tt__hheap_chunk *)
11523  hh->alloc.alloc(hh->alloc.userdata, 0,
11524  sizeof(struct nk_tt__hheap_chunk) + size * (nk_size)count);
11525  if (c == 0) return 0;
11526  c->next = hh->head;
11527  hh->head = c;
11528  hh->num_remaining_in_head_chunk = count;
11529  }
11530  --hh->num_remaining_in_head_chunk;
11531  return (char *) (hh->head) + size * (nk_size)hh->num_remaining_in_head_chunk;
11532  }
11533 }
11534 NK_INTERN void
11535 nk_tt__hheap_free(struct nk_tt__hheap *hh, void *p)
11536 {
11537  *(void **) p = hh->first_free;
11538  hh->first_free = p;
11539 }
11540 NK_INTERN void
11541 nk_tt__hheap_cleanup(struct nk_tt__hheap *hh)
11542 {
11543  struct nk_tt__hheap_chunk *c = hh->head;
11544  while (c) {
11545  struct nk_tt__hheap_chunk *n = c->next;
11546  hh->alloc.free(hh->alloc.userdata, c);
11547  c = n;
11548  }
11549 }
11550 NK_INTERN struct nk_tt__active_edge*
11551 nk_tt__new_active(struct nk_tt__hheap *hh, struct nk_tt__edge *e,
11552  int off_x, float start_point)
11553 {
11554  struct nk_tt__active_edge *z = (struct nk_tt__active_edge *)
11555  nk_tt__hheap_alloc(hh, sizeof(*z));
11556  float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
11557  /*STBTT_assert(e->y0 <= start_point); */
11558  if (!z) return z;
11559  z->fdx = dxdy;
11560  z->fdy = (dxdy != 0) ? (1/dxdy): 0;
11561  z->fx = e->x0 + dxdy * (start_point - e->y0);
11562  z->fx -= (float)off_x;
11563  z->direction = e->invert ? 1.0f : -1.0f;
11564  z->sy = e->y0;
11565  z->ey = e->y1;
11566  z->next = 0;
11567  return z;
11568 }
11569 NK_INTERN void
11570 nk_tt__handle_clipped_edge(float *scanline, int x, struct nk_tt__active_edge *e,
11571  float x0, float y0, float x1, float y1)
11572 {
11573  if (y0 == y1) return;
11574  NK_ASSERT(y0 < y1);
11575  NK_ASSERT(e->sy <= e->ey);
11576  if (y0 > e->ey) return;
11577  if (y1 < e->sy) return;
11578  if (y0 < e->sy) {
11579  x0 += (x1-x0) * (e->sy - y0) / (y1-y0);
11580  y0 = e->sy;
11581  }
11582  if (y1 > e->ey) {
11583  x1 += (x1-x0) * (e->ey - y1) / (y1-y0);
11584  y1 = e->ey;
11585  }
11586 
11587  if (x0 == x) NK_ASSERT(x1 <= x+1);
11588  else if (x0 == x+1) NK_ASSERT(x1 >= x);
11589  else if (x0 <= x) NK_ASSERT(x1 <= x);
11590  else if (x0 >= x+1) NK_ASSERT(x1 >= x+1);
11591  else NK_ASSERT(x1 >= x && x1 <= x+1);
11592 
11593  if (x0 <= x && x1 <= x)
11594  scanline[x] += e->direction * (y1-y0);
11595  else if (x0 >= x+1 && x1 >= x+1);
11596  else {
11597  NK_ASSERT(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1);
11598  /* coverage = 1 - average x position */
11599  scanline[x] += (float)e->direction * (float)(y1-y0) * (1.0f-((x0-(float)x)+(x1-(float)x))/2.0f);
11600  }
11601 }
11602 NK_INTERN void
11603 nk_tt__fill_active_edges_new(float *scanline, float *scanline_fill, int len,
11604  struct nk_tt__active_edge *e, float y_top)
11605 {
11606  float y_bottom = y_top+1;
11607  while (e)
11608  {
11609  /* brute force every pixel */
11610  /* compute intersection points with top & bottom */
11611  NK_ASSERT(e->ey >= y_top);
11612  if (e->fdx == 0) {
11613  float x0 = e->fx;
11614  if (x0 < len) {
11615  if (x0 >= 0) {
11616  nk_tt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom);
11617  nk_tt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom);
11618  } else {
11619  nk_tt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom);
11620  }
11621  }
11622  } else {
11623  float x0 = e->fx;
11624  float dx = e->fdx;
11625  float xb = x0 + dx;
11626  float x_top, x_bottom;
11627  float y0,y1;
11628  float dy = e->fdy;
11629  NK_ASSERT(e->sy <= y_bottom && e->ey >= y_top);
11630 
11631  /* compute endpoints of line segment clipped to this scanline (if the */
11632  /* line segment starts on this scanline. x0 is the intersection of the */
11633  /* line with y_top, but that may be off the line segment. */
11634  if (e->sy > y_top) {
11635  x_top = x0 + dx * (e->sy - y_top);
11636  y0 = e->sy;
11637  } else {
11638  x_top = x0;
11639  y0 = y_top;
11640  }
11641 
11642  if (e->ey < y_bottom) {
11643  x_bottom = x0 + dx * (e->ey - y_top);
11644  y1 = e->ey;
11645  } else {
11646  x_bottom = xb;
11647  y1 = y_bottom;
11648  }
11649 
11650  if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len)
11651  {
11652  /* from here on, we don't have to range check x values */
11653  if ((int) x_top == (int) x_bottom) {
11654  float height;
11655  /* simple case, only spans one pixel */
11656  int x = (int) x_top;
11657  height = y1 - y0;
11658  NK_ASSERT(x >= 0 && x < len);
11659  scanline[x] += e->direction * (1.0f-(((float)x_top - (float)x) + ((float)x_bottom-(float)x))/2.0f) * (float)height;
11660  scanline_fill[x] += e->direction * (float)height; /* everything right of this pixel is filled */
11661  } else {
11662  int x,x1,x2;
11663  float y_crossing, step, sign, area;
11664  /* covers 2+ pixels */
11665  if (x_top > x_bottom)
11666  {
11667  /* flip scanline vertically; signed area is the same */
11668  float t;
11669  y0 = y_bottom - (y0 - y_top);
11670  y1 = y_bottom - (y1 - y_top);
11671  t = y0; y0 = y1; y1 = t;
11672  t = x_bottom; x_bottom = x_top; x_top = t;
11673  dx = -dx;
11674  dy = -dy;
11675  t = x0; x0 = xb; xb = t;
11676  }
11677 
11678  x1 = (int) x_top;
11679  x2 = (int) x_bottom;
11680  /* compute intersection with y axis at x1+1 */
11681  y_crossing = ((float)x1+1 - (float)x0) * (float)dy + (float)y_top;
11682 
11683  sign = e->direction;
11684  /* area of the rectangle covered from y0..y_crossing */
11685  area = sign * (y_crossing-y0);
11686  /* area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing) */
11687  scanline[x1] += area * (1.0f-((float)((float)x_top - (float)x1)+(float)(x1+1-x1))/2.0f);
11688 
11689  step = sign * dy;
11690  for (x = x1+1; x < x2; ++x) {
11691  scanline[x] += area + step/2;
11692  area += step;
11693  }
11694  y_crossing += (float)dy * (float)(x2 - (x1+1));
11695 
11696  scanline[x2] += area + sign * (1.0f-((float)(x2-x2)+((float)x_bottom-(float)x2))/2.0f) * (y1-y_crossing);
11697  scanline_fill[x2] += sign * (y1-y0);
11698  }
11699  }
11700  else
11701  {
11702  /* if edge goes outside of box we're drawing, we require */
11703  /* clipping logic. since this does not match the intended use */
11704  /* of this library, we use a different, very slow brute */
11705  /* force implementation */
11706  int x;
11707  for (x=0; x < len; ++x)
11708  {
11709  /* cases: */
11710  /* */
11711  /* there can be up to two intersections with the pixel. any intersection */
11712  /* with left or right edges can be handled by splitting into two (or three) */
11713  /* regions. intersections with top & bottom do not necessitate case-wise logic. */
11714  /* */
11715  /* the old way of doing this found the intersections with the left & right edges, */
11716  /* then used some simple logic to produce up to three segments in sorted order */
11717  /* from top-to-bottom. however, this had a problem: if an x edge was epsilon */
11718  /* across the x border, then the corresponding y position might not be distinct */
11719  /* from the other y segment, and it might ignored as an empty segment. to avoid */
11720  /* that, we need to explicitly produce segments based on x positions. */
11721 
11722  /* rename variables to clear pairs */
11723  float ya = y_top;
11724  float x1 = (float) (x);
11725  float x2 = (float) (x+1);
11726  float x3 = xb;
11727  float y3 = y_bottom;
11728  float yb,y2;
11729 
11730  yb = ((float)x - x0) / dx + y_top;
11731  y2 = ((float)x+1 - x0) / dx + y_top;
11732 
11733  if (x0 < x1 && x3 > x2) { /* three segments descending down-right */
11734  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb);
11735  nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x2,y2);
11736  nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
11737  } else if (x3 < x1 && x0 > x2) { /* three segments descending down-left */
11738  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2);
11739  nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x1,yb);
11740  nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3);
11741  } else if (x0 < x1 && x3 > x1) { /* two segments across x, down-right */
11742  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb);
11743  nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3);
11744  } else if (x3 < x1 && x0 > x1) { /* two segments across x, down-left */
11745  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb);
11746  nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3);
11747  } else if (x0 < x2 && x3 > x2) { /* two segments across x+1, down-right */
11748  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2);
11749  nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
11750  } else if (x3 < x2 && x0 > x2) { /* two segments across x+1, down-left */
11751  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2);
11752  nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
11753  } else { /* one segment */
11754  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x3,y3);
11755  }
11756  }
11757  }
11758  }
11759  e = e->next;
11760  }
11761 }
11762 NK_INTERN void
11763 nk_tt__rasterize_sorted_edges(struct nk_tt__bitmap *result, struct nk_tt__edge *e,
11764  int n, int vsubsample, int off_x, int off_y, struct nk_allocator *alloc)
11765 {
11766  /* directly AA rasterize edges w/o supersampling */
11767  struct nk_tt__hheap hh;
11768  struct nk_tt__active_edge *active = 0;
11769  int y,j=0, i;
11770  float scanline_data[129], *scanline, *scanline2;
11771 
11772  NK_UNUSED(vsubsample);
11773  nk_zero_struct(hh);
11774  hh.alloc = *alloc;
11775 
11776  if (result->w > 64)
11777  scanline = (float *) alloc->alloc(alloc->userdata,0, (nk_size)(result->w*2+1) * sizeof(float));
11778  else scanline = scanline_data;
11779 
11780  scanline2 = scanline + result->w;
11781  y = off_y;
11782  e[n].y0 = (float) (off_y + result->h) + 1;
11783 
11784  while (j < result->h)
11785  {
11786  /* find center of pixel for this scanline */
11787  float scan_y_top = (float)y + 0.0f;
11788  float scan_y_bottom = (float)y + 1.0f;
11789  struct nk_tt__active_edge **step = &active;
11790 
11791  NK_MEMSET(scanline , 0, (nk_size)result->w*sizeof(scanline[0]));
11792  NK_MEMSET(scanline2, 0, (nk_size)(result->w+1)*sizeof(scanline[0]));
11793 
11794  /* update all active edges; */
11795  /* remove all active edges that terminate before the top of this scanline */
11796  while (*step) {
11797  struct nk_tt__active_edge * z = *step;
11798  if (z->ey <= scan_y_top) {
11799  *step = z->next; /* delete from list */
11800  NK_ASSERT(z->direction);
11801  z->direction = 0;
11802  nk_tt__hheap_free(&hh, z);
11803  } else {
11804  step = &((*step)->next); /* advance through list */
11805  }
11806  }
11807 
11808  /* insert all edges that start before the bottom of this scanline */
11809  while (e->y0 <= scan_y_bottom) {
11810  if (e->y0 != e->y1) {
11811  struct nk_tt__active_edge *z = nk_tt__new_active(&hh, e, off_x, scan_y_top);
11812  if (z != 0) {
11813  NK_ASSERT(z->ey >= scan_y_top);
11814  /* insert at front */
11815  z->next = active;
11816  active = z;
11817  }
11818  }
11819  ++e;
11820  }
11821 
11822  /* now process all active edges */
11823  if (active)
11824  nk_tt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top);
11825 
11826  {
11827  float sum = 0;
11828  for (i=0; i < result->w; ++i) {
11829  float k;
11830  int m;
11831  sum += scanline2[i];
11832  k = scanline[i] + sum;
11833  k = (float) NK_ABS(k) * 255.0f + 0.5f;
11834  m = (int) k;
11835  if (m > 255) m = 255;
11836  result->pixels[j*result->stride + i] = (unsigned char) m;
11837  }
11838  }
11839  /* advance all the edges */
11840  step = &active;
11841  while (*step) {
11842  struct nk_tt__active_edge *z = *step;
11843  z->fx += z->fdx; /* advance to position for current scanline */
11844  step = &((*step)->next); /* advance through list */
11845  }
11846  ++y;
11847  ++j;
11848  }
11849  nk_tt__hheap_cleanup(&hh);
11850  if (scanline != scanline_data)
11851  alloc->free(alloc->userdata, scanline);
11852 }
11853 NK_INTERN void
11854 nk_tt__sort_edges_ins_sort(struct nk_tt__edge *p, int n)
11855 {
11856  int i,j;
11857  #define NK_TT__COMPARE(a,b) ((a)->y0 < (b)->y0)
11858  for (i=1; i < n; ++i) {
11859  struct nk_tt__edge t = p[i], *a = &t;
11860  j = i;
11861  while (j > 0) {
11862  struct nk_tt__edge *b = &p[j-1];
11863  int c = NK_TT__COMPARE(a,b);
11864  if (!c) break;
11865  p[j] = p[j-1];
11866  --j;
11867  }
11868  if (i != j)
11869  p[j] = t;
11870  }
11871 }
11872 NK_INTERN void
11873 nk_tt__sort_edges_quicksort(struct nk_tt__edge *p, int n)
11874 {
11875  /* threshold for transitioning to insertion sort */
11876  while (n > 12) {
11877  struct nk_tt__edge t;
11878  int c01,c12,c,m,i,j;
11879 
11880  /* compute median of three */
11881  m = n >> 1;
11882  c01 = NK_TT__COMPARE(&p[0],&p[m]);
11883  c12 = NK_TT__COMPARE(&p[m],&p[n-1]);
11884 
11885  /* if 0 >= mid >= end, or 0 < mid < end, then use mid */
11886  if (c01 != c12) {
11887  /* otherwise, we'll need to swap something else to middle */
11888  int z;
11889  c = NK_TT__COMPARE(&p[0],&p[n-1]);
11890  /* 0>mid && mid<n: 0>n => n; 0<n => 0 */
11891  /* 0<mid && mid>n: 0>n => 0; 0<n => n */
11892  z = (c == c12) ? 0 : n-1;
11893  t = p[z];
11894  p[z] = p[m];
11895  p[m] = t;
11896  }
11897 
11898  /* now p[m] is the median-of-three */
11899  /* swap it to the beginning so it won't move around */
11900  t = p[0];
11901  p[0] = p[m];
11902  p[m] = t;
11903 
11904  /* partition loop */
11905  i=1;
11906  j=n-1;
11907  for(;;) {
11908  /* handling of equality is crucial here */
11909  /* for sentinels & efficiency with duplicates */
11910  for (;;++i) {
11911  if (!NK_TT__COMPARE(&p[i], &p[0])) break;
11912  }
11913  for (;;--j) {
11914  if (!NK_TT__COMPARE(&p[0], &p[j])) break;
11915  }
11916 
11917  /* make sure we haven't crossed */
11918  if (i >= j) break;
11919  t = p[i];
11920  p[i] = p[j];
11921  p[j] = t;
11922 
11923  ++i;
11924  --j;
11925 
11926  }
11927 
11928  /* recurse on smaller side, iterate on larger */
11929  if (j < (n-i)) {
11930  nk_tt__sort_edges_quicksort(p,j);
11931  p = p+i;
11932  n = n-i;
11933  } else {
11934  nk_tt__sort_edges_quicksort(p+i, n-i);
11935  n = j;
11936  }
11937  }
11938 }
11939 NK_INTERN void
11940 nk_tt__sort_edges(struct nk_tt__edge *p, int n)
11941 {
11942  nk_tt__sort_edges_quicksort(p, n);
11943  nk_tt__sort_edges_ins_sort(p, n);
11944 }
11945 NK_INTERN void
11946 nk_tt__rasterize(struct nk_tt__bitmap *result, struct nk_tt__point *pts,
11947  int *wcount, int windings, float scale_x, float scale_y,
11948  float shift_x, float shift_y, int off_x, int off_y, int invert,
11949  struct nk_allocator *alloc)
11950 {
11951  float y_scale_inv = invert ? -scale_y : scale_y;
11952  struct nk_tt__edge *e;
11953  int n,i,j,k,m;
11954  int vsubsample = 1;
11955  /* vsubsample should divide 255 evenly; otherwise we won't reach full opacity */
11956 
11957  /* now we have to blow out the windings into explicit edge lists */
11958  n = 0;
11959  for (i=0; i < windings; ++i)
11960  n += wcount[i];
11961 
11962  e = (struct nk_tt__edge*)
11963  alloc->alloc(alloc->userdata, 0,(sizeof(*e) * (nk_size)(n+1)));
11964  if (e == 0) return;
11965  n = 0;
11966 
11967  m=0;
11968  for (i=0; i < windings; ++i)
11969  {
11970  struct nk_tt__point *p = pts + m;
11971  m += wcount[i];
11972  j = wcount[i]-1;
11973  for (k=0; k < wcount[i]; j=k++) {
11974  int a=k,b=j;
11975  /* skip the edge if horizontal */
11976  if (p[j].y == p[k].y)
11977  continue;
11978 
11979  /* add edge from j to k to the list */
11980  e[n].invert = 0;
11981  if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
11982  e[n].invert = 1;
11983  a=j,b=k;
11984  }
11985  e[n].x0 = p[a].x * scale_x + shift_x;
11986  e[n].y0 = (p[a].y * y_scale_inv + shift_y) * (float)vsubsample;
11987  e[n].x1 = p[b].x * scale_x + shift_x;
11988  e[n].y1 = (p[b].y * y_scale_inv + shift_y) * (float)vsubsample;
11989  ++n;
11990  }
11991  }
11992 
11993  /* now sort the edges by their highest point (should snap to integer, and then by x) */
11994  /*STBTT_sort(e, n, sizeof(e[0]), nk_tt__edge_compare); */
11995  nk_tt__sort_edges(e, n);
11996  /* now, traverse the scanlines and find the intersections on each scanline, use xor winding rule */
11997  nk_tt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, alloc);
11998  alloc->free(alloc->userdata, e);
11999 }
12000 NK_INTERN void
12001 nk_tt__add_point(struct nk_tt__point *points, int n, float x, float y)
12002 {
12003  if (!points) return; /* during first pass, it's unallocated */
12004  points[n].x = x;
12005  points[n].y = y;
12006 }
12007 NK_INTERN int
12008 nk_tt__tesselate_curve(struct nk_tt__point *points, int *num_points,
12009  float x0, float y0, float x1, float y1, float x2, float y2,
12010  float objspace_flatness_squared, int n)
12011 {
12012  /* tesselate until threshold p is happy...
12013  * @TODO warped to compensate for non-linear stretching */
12014  /* midpoint */
12015  float mx = (x0 + 2*x1 + x2)/4;
12016  float my = (y0 + 2*y1 + y2)/4;
12017  /* versus directly drawn line */
12018  float dx = (x0+x2)/2 - mx;
12019  float dy = (y0+y2)/2 - my;
12020  if (n > 16) /* 65536 segments on one curve better be enough! */
12021  return 1;
12022 
12023  /* half-pixel error allowed... need to be smaller if AA */
12024  if (dx*dx+dy*dy > objspace_flatness_squared) {
12025  nk_tt__tesselate_curve(points, num_points, x0,y0,
12026  (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);
12027  nk_tt__tesselate_curve(points, num_points, mx,my,
12028  (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);
12029  } else {
12030  nk_tt__add_point(points, *num_points,x2,y2);
12031  *num_points = *num_points+1;
12032  }
12033  return 1;
12034 }
12035 NK_INTERN struct nk_tt__point*
12036 nk_tt_FlattenCurves(struct nk_tt_vertex *vertices, int num_verts,
12037  float objspace_flatness, int **contour_lengths, int *num_contours,
12038  struct nk_allocator *alloc)
12039 {
12040  /* returns number of contours */
12041  struct nk_tt__point *points=0;
12042  int num_points=0;
12043  float objspace_flatness_squared = objspace_flatness * objspace_flatness;
12044  int i;
12045  int n=0;
12046  int start=0;
12047  int pass;
12048 
12049  /* count how many "moves" there are to get the contour count */
12050  for (i=0; i < num_verts; ++i)
12051  if (vertices[i].type == NK_TT_vmove) ++n;
12052 
12053  *num_contours = n;
12054  if (n == 0) return 0;
12055 
12056  *contour_lengths = (int *)
12057  alloc->alloc(alloc->userdata,0, (sizeof(**contour_lengths) * (nk_size)n));
12058  if (*contour_lengths == 0) {
12059  *num_contours = 0;
12060  return 0;
12061  }
12062 
12063  /* make two passes through the points so we don't need to realloc */
12064  for (pass=0; pass < 2; ++pass)
12065  {
12066  float x=0,y=0;
12067  if (pass == 1) {
12068  points = (struct nk_tt__point *)
12069  alloc->alloc(alloc->userdata,0, (nk_size)num_points * sizeof(points[0]));
12070  if (points == 0) goto error;
12071  }
12072  num_points = 0;
12073  n= -1;
12074 
12075  for (i=0; i < num_verts; ++i)
12076  {
12077  switch (vertices[i].type) {
12078  case NK_TT_vmove:
12079  /* start the next contour */
12080  if (n >= 0)
12081  (*contour_lengths)[n] = num_points - start;
12082  ++n;
12083  start = num_points;
12084 
12085  x = vertices[i].x, y = vertices[i].y;
12086  nk_tt__add_point(points, num_points++, x,y);
12087  break;
12088  case NK_TT_vline:
12089  x = vertices[i].x, y = vertices[i].y;
12090  nk_tt__add_point(points, num_points++, x, y);
12091  break;
12092  case NK_TT_vcurve:
12093  nk_tt__tesselate_curve(points, &num_points, x,y,
12094  vertices[i].cx, vertices[i].cy,
12095  vertices[i].x, vertices[i].y,
12096  objspace_flatness_squared, 0);
12097  x = vertices[i].x, y = vertices[i].y;
12098  break;
12099  default: break;
12100  }
12101  }
12102  (*contour_lengths)[n] = num_points - start;
12103  }
12104  return points;
12105 
12106 error:
12107  alloc->free(alloc->userdata, points);
12108  alloc->free(alloc->userdata, *contour_lengths);
12109  *contour_lengths = 0;
12110  *num_contours = 0;
12111  return 0;
12112 }
12113 NK_INTERN void
12114 nk_tt_Rasterize(struct nk_tt__bitmap *result, float flatness_in_pixels,
12115  struct nk_tt_vertex *vertices, int num_verts,
12116  float scale_x, float scale_y, float shift_x, float shift_y,
12117  int x_off, int y_off, int invert, struct nk_allocator *alloc)
12118 {
12119  float scale = scale_x > scale_y ? scale_y : scale_x;
12120  int winding_count, *winding_lengths;
12121  struct nk_tt__point *windings = nk_tt_FlattenCurves(vertices, num_verts,
12122  flatness_in_pixels / scale, &winding_lengths, &winding_count, alloc);
12123 
12124  NK_ASSERT(alloc);
12125  if (windings) {
12126  nk_tt__rasterize(result, windings, winding_lengths, winding_count,
12127  scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, alloc);
12128  alloc->free(alloc->userdata, winding_lengths);
12129  alloc->free(alloc->userdata, windings);
12130  }
12131 }
12132 NK_INTERN void
12133 nk_tt_MakeGlyphBitmapSubpixel(const struct nk_tt_fontinfo *info, unsigned char *output,
12134  int out_w, int out_h, int out_stride, float scale_x, float scale_y,
12135  float shift_x, float shift_y, int glyph, struct nk_allocator *alloc)
12136 {
12137  int ix0,iy0;
12138  struct nk_tt_vertex *vertices;
12139  int num_verts = nk_tt_GetGlyphShape(info, alloc, glyph, &vertices);
12140  struct nk_tt__bitmap gbm;
12141 
12142  nk_tt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x,
12143  shift_y, &ix0,&iy0,0,0);
12144  gbm.pixels = output;
12145  gbm.w = out_w;
12146  gbm.h = out_h;
12147  gbm.stride = out_stride;
12148 
12149  if (gbm.w && gbm.h)
12150  nk_tt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y,
12151  shift_x, shift_y, ix0,iy0, 1, alloc);
12152  alloc->free(alloc->userdata, vertices);
12153 }
12154 
12155 /*-------------------------------------------------------------
12156  * Bitmap baking
12157  * --------------------------------------------------------------*/
12158 NK_INTERN int
12159 nk_tt_PackBegin(struct nk_tt_pack_context *spc, unsigned char *pixels,
12160  int pw, int ph, int stride_in_bytes, int padding, struct nk_allocator *alloc)
12161 {
12162  int num_nodes = pw - padding;
12163  struct nk_rp_context *context = (struct nk_rp_context *)
12164  alloc->alloc(alloc->userdata,0, sizeof(*context));
12165  struct nk_rp_node *nodes = (struct nk_rp_node*)
12166  alloc->alloc(alloc->userdata,0, (sizeof(*nodes ) * (nk_size)num_nodes));
12167 
12168  if (context == 0 || nodes == 0) {
12169  if (context != 0) alloc->free(alloc->userdata, context);
12170  if (nodes != 0) alloc->free(alloc->userdata, nodes);
12171  return 0;
12172  }
12173 
12174  spc->width = pw;
12175  spc->height = ph;
12176  spc->pixels = pixels;
12177  spc->pack_info = context;
12178  spc->nodes = nodes;
12179  spc->padding = padding;
12180  spc->stride_in_bytes = (stride_in_bytes != 0) ? stride_in_bytes : pw;
12181  spc->h_oversample = 1;
12182  spc->v_oversample = 1;
12183 
12184  nk_rp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
12185  if (pixels)
12186  NK_MEMSET(pixels, 0, (nk_size)(pw*ph)); /* background of 0 around pixels */
12187  return 1;
12188 }
12189 NK_INTERN void
12190 nk_tt_PackEnd(struct nk_tt_pack_context *spc, struct nk_allocator *alloc)
12191 {
12192  alloc->free(alloc->userdata, spc->nodes);
12193  alloc->free(alloc->userdata, spc->pack_info);
12194 }
12195 NK_INTERN void
12196 nk_tt_PackSetOversampling(struct nk_tt_pack_context *spc,
12197  unsigned int h_oversample, unsigned int v_oversample)
12198 {
12199  NK_ASSERT(h_oversample <= NK_TT_MAX_OVERSAMPLE);
12200  NK_ASSERT(v_oversample <= NK_TT_MAX_OVERSAMPLE);
12201  if (h_oversample <= NK_TT_MAX_OVERSAMPLE)
12202  spc->h_oversample = h_oversample;
12203  if (v_oversample <= NK_TT_MAX_OVERSAMPLE)
12204  spc->v_oversample = v_oversample;
12205 }
12206 NK_INTERN void
12207 nk_tt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes,
12208  int kernel_width)
12209 {
12210  unsigned char buffer[NK_TT_MAX_OVERSAMPLE];
12211  int safe_w = w - kernel_width;
12212  int j;
12213 
12214  for (j=0; j < h; ++j)
12215  {
12216  int i;
12217  unsigned int total;
12218  NK_MEMSET(buffer, 0, (nk_size)kernel_width);
12219 
12220  total = 0;
12221 
12222  /* make kernel_width a constant in common cases so compiler can optimize out the divide */
12223  switch (kernel_width) {
12224  case 2:
12225  for (i=0; i <= safe_w; ++i) {
12226  total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
12227  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
12228  pixels[i] = (unsigned char) (total / 2);
12229  }
12230  break;
12231  case 3:
12232  for (i=0; i <= safe_w; ++i) {
12233  total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
12234  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
12235  pixels[i] = (unsigned char) (total / 3);
12236  }
12237  break;
12238  case 4:
12239  for (i=0; i <= safe_w; ++i) {
12240  total += (unsigned int)pixels[i] - buffer[i & NK_TT__OVER_MASK];
12241  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
12242  pixels[i] = (unsigned char) (total / 4);
12243  }
12244  break;
12245  case 5:
12246  for (i=0; i <= safe_w; ++i) {
12247  total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
12248  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
12249  pixels[i] = (unsigned char) (total / 5);
12250  }
12251  break;
12252  default:
12253  for (i=0; i <= safe_w; ++i) {
12254  total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
12255  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
12256  pixels[i] = (unsigned char) (total / (unsigned int)kernel_width);
12257  }
12258  break;
12259  }
12260 
12261  for (; i < w; ++i) {
12262  NK_ASSERT(pixels[i] == 0);
12263  total -= (unsigned int)(buffer[i & NK_TT__OVER_MASK]);
12264  pixels[i] = (unsigned char) (total / (unsigned int)kernel_width);
12265  }
12266  pixels += stride_in_bytes;
12267  }
12268 }
12269 NK_INTERN void
12270 nk_tt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes,
12271  int kernel_width)
12272 {
12273  unsigned char buffer[NK_TT_MAX_OVERSAMPLE];
12274  int safe_h = h - kernel_width;
12275  int j;
12276 
12277  for (j=0; j < w; ++j)
12278  {
12279  int i;
12280  unsigned int total;
12281  NK_MEMSET(buffer, 0, (nk_size)kernel_width);
12282 
12283  total = 0;
12284 
12285  /* make kernel_width a constant in common cases so compiler can optimize out the divide */
12286  switch (kernel_width) {
12287  case 2:
12288  for (i=0; i <= safe_h; ++i) {
12289  total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
12290  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
12291  pixels[i*stride_in_bytes] = (unsigned char) (total / 2);
12292  }
12293  break;
12294  case 3:
12295  for (i=0; i <= safe_h; ++i) {
12296  total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
12297  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
12298  pixels[i*stride_in_bytes] = (unsigned char) (total / 3);
12299  }
12300  break;
12301  case 4:
12302  for (i=0; i <= safe_h; ++i) {
12303  total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
12304  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
12305  pixels[i*stride_in_bytes] = (unsigned char) (total / 4);
12306  }
12307  break;
12308  case 5:
12309  for (i=0; i <= safe_h; ++i) {
12310  total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
12311  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
12312  pixels[i*stride_in_bytes] = (unsigned char) (total / 5);
12313  }
12314  break;
12315  default:
12316  for (i=0; i <= safe_h; ++i) {
12317  total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
12318  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
12319  pixels[i*stride_in_bytes] = (unsigned char) (total / (unsigned int)kernel_width);
12320  }
12321  break;
12322  }
12323 
12324  for (; i < h; ++i) {
12325  NK_ASSERT(pixels[i*stride_in_bytes] == 0);
12326  total -= (unsigned int)(buffer[i & NK_TT__OVER_MASK]);
12327  pixels[i*stride_in_bytes] = (unsigned char) (total / (unsigned int)kernel_width);
12328  }
12329  pixels += 1;
12330  }
12331 }
12332 NK_INTERN float
12333 nk_tt__oversample_shift(int oversample)
12334 {
12335  if (!oversample)
12336  return 0.0f;
12337 
12338  /* The prefilter is a box filter of width "oversample", */
12339  /* which shifts phase by (oversample - 1)/2 pixels in */
12340  /* oversampled space. We want to shift in the opposite */
12341  /* direction to counter this. */
12342  return (float)-(oversample - 1) / (2.0f * (float)oversample);
12343 }
12344 NK_INTERN int
12345 nk_tt_PackFontRangesGatherRects(struct nk_tt_pack_context *spc,
12346  struct nk_tt_fontinfo *info, struct nk_tt_pack_range *ranges,
12347  int num_ranges, struct nk_rp_rect *rects)
12348 {
12349  /* rects array must be big enough to accommodate all characters in the given ranges */
12350  int i,j,k;
12351  k = 0;
12352 
12353  for (i=0; i < num_ranges; ++i) {
12354  float fh = ranges[i].font_size;
12355  float scale = (fh > 0) ? nk_tt_ScaleForPixelHeight(info, fh):
12356  nk_tt_ScaleForMappingEmToPixels(info, -fh);
12357  ranges[i].h_oversample = (unsigned char) spc->h_oversample;
12358  ranges[i].v_oversample = (unsigned char) spc->v_oversample;
12359  for (j=0; j < ranges[i].num_chars; ++j) {
12360  int x0,y0,x1,y1;
12361  int codepoint = ranges[i].first_unicode_codepoint_in_range ?
12362  ranges[i].first_unicode_codepoint_in_range + j :
12363  ranges[i].array_of_unicode_codepoints[j];
12364 
12365  int glyph = nk_tt_FindGlyphIndex(info, codepoint);
12366  nk_tt_GetGlyphBitmapBoxSubpixel(info,glyph, scale * (float)spc->h_oversample,
12367  scale * (float)spc->v_oversample, 0,0, &x0,&y0,&x1,&y1);
12368  rects[k].w = (nk_rp_coord) (x1-x0 + spc->padding + (int)spc->h_oversample-1);
12369  rects[k].h = (nk_rp_coord) (y1-y0 + spc->padding + (int)spc->v_oversample-1);
12370  ++k;
12371  }
12372  }
12373  return k;
12374 }
12375 NK_INTERN int
12376 nk_tt_PackFontRangesRenderIntoRects(struct nk_tt_pack_context *spc,
12377  struct nk_tt_fontinfo *info, struct nk_tt_pack_range *ranges,
12378  int num_ranges, struct nk_rp_rect *rects, struct nk_allocator *alloc)
12379 {
12380  int i,j,k, return_value = 1;
12381  /* save current values */
12382  int old_h_over = (int)spc->h_oversample;
12383  int old_v_over = (int)spc->v_oversample;
12384  /* rects array must be big enough to accommodate all characters in the given ranges */
12385 
12386  k = 0;
12387  for (i=0; i < num_ranges; ++i)
12388  {
12389  float fh = ranges[i].font_size;
12390  float recip_h,recip_v,sub_x,sub_y;
12391  float scale = fh > 0 ? nk_tt_ScaleForPixelHeight(info, fh):
12392  nk_tt_ScaleForMappingEmToPixels(info, -fh);
12393 
12394  spc->h_oversample = ranges[i].h_oversample;
12395  spc->v_oversample = ranges[i].v_oversample;
12396 
12397  recip_h = 1.0f / (float)spc->h_oversample;
12398  recip_v = 1.0f / (float)spc->v_oversample;
12399 
12400  sub_x = nk_tt__oversample_shift((int)spc->h_oversample);
12401  sub_y = nk_tt__oversample_shift((int)spc->v_oversample);
12402 
12403  for (j=0; j < ranges[i].num_chars; ++j)
12404  {
12405  struct nk_rp_rect *r = &rects[k];
12406  if (r->was_packed)
12407  {
12408  struct nk_tt_packedchar *bc = &ranges[i].chardata_for_range[j];
12409  int advance, lsb, x0,y0,x1,y1;
12410  int codepoint = ranges[i].first_unicode_codepoint_in_range ?
12411  ranges[i].first_unicode_codepoint_in_range + j :
12412  ranges[i].array_of_unicode_codepoints[j];
12413  int glyph = nk_tt_FindGlyphIndex(info, codepoint);
12414  nk_rp_coord pad = (nk_rp_coord) spc->padding;
12415 
12416  /* pad on left and top */
12417  r->x = (nk_rp_coord)((int)r->x + (int)pad);
12418  r->y = (nk_rp_coord)((int)r->y + (int)pad);
12419  r->w = (nk_rp_coord)((int)r->w - (int)pad);
12420  r->h = (nk_rp_coord)((int)r->h - (int)pad);
12421 
12422  nk_tt_GetGlyphHMetrics(info, glyph, &advance, &lsb);
12423  nk_tt_GetGlyphBitmapBox(info, glyph, scale * (float)spc->h_oversample,
12424  (scale * (float)spc->v_oversample), &x0,&y0,&x1,&y1);
12425  nk_tt_MakeGlyphBitmapSubpixel(info, spc->pixels + r->x + r->y*spc->stride_in_bytes,
12426  (int)(r->w - spc->h_oversample+1), (int)(r->h - spc->v_oversample+1),
12427  spc->stride_in_bytes, scale * (float)spc->h_oversample,
12428  scale * (float)spc->v_oversample, 0,0, glyph, alloc);
12429 
12430  if (spc->h_oversample > 1)
12431  nk_tt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
12432  r->w, r->h, spc->stride_in_bytes, (int)spc->h_oversample);
12433 
12434  if (spc->v_oversample > 1)
12435  nk_tt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
12436  r->w, r->h, spc->stride_in_bytes, (int)spc->v_oversample);
12437 
12438  bc->x0 = (nk_ushort) r->x;
12439  bc->y0 = (nk_ushort) r->y;
12440  bc->x1 = (nk_ushort) (r->x + r->w);
12441  bc->y1 = (nk_ushort) (r->y + r->h);
12442  bc->xadvance = scale * (float)advance;
12443  bc->xoff = (float) x0 * recip_h + sub_x;
12444  bc->yoff = (float) y0 * recip_v + sub_y;
12445  bc->xoff2 = ((float)x0 + r->w) * recip_h + sub_x;
12446  bc->yoff2 = ((float)y0 + r->h) * recip_v + sub_y;
12447  } else {
12448  return_value = 0; /* if any fail, report failure */
12449  }
12450  ++k;
12451  }
12452  }
12453  /* restore original values */
12454  spc->h_oversample = (unsigned int)old_h_over;
12455  spc->v_oversample = (unsigned int)old_v_over;
12456  return return_value;
12457 }
12458 NK_INTERN void
12459 nk_tt_GetPackedQuad(struct nk_tt_packedchar *chardata, int pw, int ph,
12460  int char_index, float *xpos, float *ypos, struct nk_tt_aligned_quad *q,
12461  int align_to_integer)
12462 {
12463  float ipw = 1.0f / (float)pw, iph = 1.0f / (float)ph;
12464  struct nk_tt_packedchar *b = (struct nk_tt_packedchar*)(chardata + char_index);
12465  if (align_to_integer) {
12466  int tx = nk_ifloorf((*xpos + b->xoff) + 0.5f);
12467  int ty = nk_ifloorf((*ypos + b->yoff) + 0.5f);
12468 
12469  float x = (float)tx;
12470  float y = (float)ty;
12471 
12472  q->x0 = x;
12473  q->y0 = y;
12474  q->x1 = x + b->xoff2 - b->xoff;
12475  q->y1 = y + b->yoff2 - b->yoff;
12476  } else {
12477  q->x0 = *xpos + b->xoff;
12478  q->y0 = *ypos + b->yoff;
12479  q->x1 = *xpos + b->xoff2;
12480  q->y1 = *ypos + b->yoff2;
12481  }
12482  q->s0 = b->x0 * ipw;
12483  q->t0 = b->y0 * iph;
12484  q->s1 = b->x1 * ipw;
12485  q->t1 = b->y1 * iph;
12486  *xpos += b->xadvance;
12487 }
12488 
12489 /* -------------------------------------------------------------
12490  *
12491  * FONT BAKING
12492  *
12493  * --------------------------------------------------------------*/
12494 struct nk_font_bake_data {
12495  struct nk_tt_fontinfo info;
12496  struct nk_rp_rect *rects;
12497  struct nk_tt_pack_range *ranges;
12498  nk_rune range_count;
12499 };
12500 
12501 struct nk_font_baker {
12502  struct nk_allocator alloc;
12503  struct nk_tt_pack_context spc;
12504  struct nk_font_bake_data *build;
12505  struct nk_tt_packedchar *packed_chars;
12506  struct nk_rp_rect *rects;
12507  struct nk_tt_pack_range *ranges;
12508 };
12509 
12510 NK_GLOBAL const nk_size nk_rect_align = NK_ALIGNOF(struct nk_rp_rect);
12511 NK_GLOBAL const nk_size nk_range_align = NK_ALIGNOF(struct nk_tt_pack_range);
12512 NK_GLOBAL const nk_size nk_char_align = NK_ALIGNOF(struct nk_tt_packedchar);
12513 NK_GLOBAL const nk_size nk_build_align = NK_ALIGNOF(struct nk_font_bake_data);
12514 NK_GLOBAL const nk_size nk_baker_align = NK_ALIGNOF(struct nk_font_baker);
12515 
12516 NK_INTERN int
12517 nk_range_count(const nk_rune *range)
12518 {
12519  const nk_rune *iter = range;
12520  NK_ASSERT(range);
12521  if (!range) return 0;
12522  while (*(iter++) != 0);
12523  return (iter == range) ? 0 : (int)((iter - range)/2);
12524 }
12525 NK_INTERN int
12526 nk_range_glyph_count(const nk_rune *range, int count)
12527 {
12528  int i = 0;
12529  int total_glyphs = 0;
12530  for (i = 0; i < count; ++i) {
12531  int diff;
12532  nk_rune f = range[(i*2)+0];
12533  nk_rune t = range[(i*2)+1];
12534  NK_ASSERT(t >= f);
12535  diff = (int)((t - f) + 1);
12536  total_glyphs += diff;
12537  }
12538  return total_glyphs;
12539 }
12540 NK_API const nk_rune*
12541 nk_font_default_glyph_ranges(void)
12542 {
12543  NK_STORAGE const nk_rune ranges[] = {0x0020, 0x00FF, 0};
12544  return ranges;
12545 }
12546 NK_API const nk_rune*
12547 nk_font_chinese_glyph_ranges(void)
12548 {
12549  NK_STORAGE const nk_rune ranges[] = {
12550  0x0020, 0x00FF,
12551  0x3000, 0x30FF,
12552  0x31F0, 0x31FF,
12553  0xFF00, 0xFFEF,
12554  0x4e00, 0x9FAF,
12555  0
12556  };
12557  return ranges;
12558 }
12559 NK_API const nk_rune*
12560 nk_font_cyrillic_glyph_ranges(void)
12561 {
12562  NK_STORAGE const nk_rune ranges[] = {
12563  0x0020, 0x00FF,
12564  0x0400, 0x052F,
12565  0x2DE0, 0x2DFF,
12566  0xA640, 0xA69F,
12567  0
12568  };
12569  return ranges;
12570 }
12571 NK_API const nk_rune*
12572 nk_font_korean_glyph_ranges(void)
12573 {
12574  NK_STORAGE const nk_rune ranges[] = {
12575  0x0020, 0x00FF,
12576  0x3131, 0x3163,
12577  0xAC00, 0xD79D,
12578  0
12579  };
12580  return ranges;
12581 }
12582 NK_INTERN void
12583 nk_font_baker_memory(nk_size *temp, int *glyph_count,
12584  struct nk_font_config *config_list, int count)
12585 {
12586  int range_count = 0;
12587  int total_range_count = 0;
12588  struct nk_font_config *iter, *i;
12589 
12590  NK_ASSERT(config_list);
12591  NK_ASSERT(glyph_count);
12592  if (!config_list) {
12593  *temp = 0;
12594  *glyph_count = 0;
12595  return;
12596  }
12597  *glyph_count = 0;
12598  for (iter = config_list; iter; iter = iter->next) {
12599  i = iter;
12600  do {if (!i->range) iter->range = nk_font_default_glyph_ranges();
12601  range_count = nk_range_count(i->range);
12602  total_range_count += range_count;
12603  *glyph_count += nk_range_glyph_count(i->range, range_count);
12604  } while ((i = i->n) != iter);
12605  }
12606  *temp = (nk_size)*glyph_count * sizeof(struct nk_rp_rect);
12607  *temp += (nk_size)total_range_count * sizeof(struct nk_tt_pack_range);
12608  *temp += (nk_size)*glyph_count * sizeof(struct nk_tt_packedchar);
12609  *temp += (nk_size)count * sizeof(struct nk_font_bake_data);
12610  *temp += sizeof(struct nk_font_baker);
12611  *temp += nk_rect_align + nk_range_align + nk_char_align;
12612  *temp += nk_build_align + nk_baker_align;
12613 }
12614 NK_INTERN struct nk_font_baker*
12615 nk_font_baker(void *memory, int glyph_count, int count, struct nk_allocator *alloc)
12616 {
12617  struct nk_font_baker *baker;
12618  if (!memory) return 0;
12619  /* setup baker inside a memory block */
12620  baker = (struct nk_font_baker*)NK_ALIGN_PTR(memory, nk_baker_align);
12621  baker->build = (struct nk_font_bake_data*)NK_ALIGN_PTR((baker + 1), nk_build_align);
12622  baker->packed_chars = (struct nk_tt_packedchar*)NK_ALIGN_PTR((baker->build + count), nk_char_align);
12623  baker->rects = (struct nk_rp_rect*)NK_ALIGN_PTR((baker->packed_chars + glyph_count), nk_rect_align);
12624  baker->ranges = (struct nk_tt_pack_range*)NK_ALIGN_PTR((baker->rects + glyph_count), nk_range_align);
12625  baker->alloc = *alloc;
12626  return baker;
12627 }
12628 NK_INTERN int
12629 nk_font_bake_pack(struct nk_font_baker *baker,
12630  nk_size *image_memory, int *width, int *height, struct nk_recti *custom,
12631  const struct nk_font_config *config_list, int count,
12632  struct nk_allocator *alloc)
12633 {
12634  NK_STORAGE const nk_size max_height = 1024 * 32;
12635  const struct nk_font_config *config_iter, *it;
12636  int total_glyph_count = 0;
12637  int total_range_count = 0;
12638  int range_count = 0;
12639  int i = 0;
12640 
12641  NK_ASSERT(image_memory);
12642  NK_ASSERT(width);
12643  NK_ASSERT(height);
12644  NK_ASSERT(config_list);
12645  NK_ASSERT(count);
12646  NK_ASSERT(alloc);
12647 
12648  if (!image_memory || !width || !height || !config_list || !count) return nk_false;
12649  for (config_iter = config_list; config_iter; config_iter = config_iter->next) {
12650  it = config_iter;
12651  do {range_count = nk_range_count(it->range);
12652  total_range_count += range_count;
12653  total_glyph_count += nk_range_glyph_count(it->range, range_count);
12654  } while ((it = it->n) != config_iter);
12655  }
12656  /* setup font baker from temporary memory */
12657  for (config_iter = config_list; config_iter; config_iter = config_iter->next) {
12658  it = config_iter;
12659  do {if (!nk_tt_InitFont(&baker->build[i++].info, (const unsigned char*)it->ttf_blob, 0))
12660  return nk_false;
12661  } while ((it = it->n) != config_iter);
12662  }
12663  *height = 0;
12664  *width = (total_glyph_count > 1000) ? 1024 : 512;
12665  nk_tt_PackBegin(&baker->spc, 0, (int)*width, (int)max_height, 0, 1, alloc);
12666  {
12667  int input_i = 0;
12668  int range_n = 0;
12669  int rect_n = 0;
12670  int char_n = 0;
12671 
12672  if (custom) {
12673  /* pack custom user data first so it will be in the upper left corner*/
12674  struct nk_rp_rect custom_space;
12675  nk_zero(&custom_space, sizeof(custom_space));
12676  custom_space.w = (nk_rp_coord)(custom->w);
12677  custom_space.h = (nk_rp_coord)(custom->h);
12678 
12679  nk_tt_PackSetOversampling(&baker->spc, 1, 1);
12680  nk_rp_pack_rects((struct nk_rp_context*)baker->spc.pack_info, &custom_space, 1);
12681  *height = NK_MAX(*height, (int)(custom_space.y + custom_space.h));
12682 
12683  custom->x = (short)custom_space.x;
12684  custom->y = (short)custom_space.y;
12685  custom->w = (short)custom_space.w;
12686  custom->h = (short)custom_space.h;
12687  }
12688 
12689  /* first font pass: pack all glyphs */
12690  for (input_i = 0, config_iter = config_list; input_i < count && config_iter;
12691  config_iter = config_iter->next) {
12692  it = config_iter;
12693  do {int n = 0;
12694  int glyph_count;
12695  const nk_rune *in_range;
12696  const struct nk_font_config *cfg = it;
12697  struct nk_font_bake_data *tmp = &baker->build[input_i++];
12698 
12699  /* count glyphs + ranges in current font */
12700  glyph_count = 0; range_count = 0;
12701  for (in_range = cfg->range; in_range[0] && in_range[1]; in_range += 2) {
12702  glyph_count += (int)(in_range[1] - in_range[0]) + 1;
12703  range_count++;
12704  }
12705 
12706  /* setup ranges */
12707  tmp->ranges = baker->ranges + range_n;
12708  tmp->range_count = (nk_rune)range_count;
12709  range_n += range_count;
12710  for (i = 0; i < range_count; ++i) {
12711  in_range = &cfg->range[i * 2];
12712  tmp->ranges[i].font_size = cfg->size;
12713  tmp->ranges[i].first_unicode_codepoint_in_range = (int)in_range[0];
12714  tmp->ranges[i].num_chars = (int)(in_range[1]- in_range[0]) + 1;
12715  tmp->ranges[i].chardata_for_range = baker->packed_chars + char_n;
12716  char_n += tmp->ranges[i].num_chars;
12717  }
12718 
12719  /* pack */
12720  tmp->rects = baker->rects + rect_n;
12721  rect_n += glyph_count;
12722  nk_tt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v);
12723  n = nk_tt_PackFontRangesGatherRects(&baker->spc, &tmp->info,
12724  tmp->ranges, (int)tmp->range_count, tmp->rects);
12725  nk_rp_pack_rects((struct nk_rp_context*)baker->spc.pack_info, tmp->rects, (int)n);
12726 
12727  /* texture height */
12728  for (i = 0; i < n; ++i) {
12729  if (tmp->rects[i].was_packed)
12730  *height = NK_MAX(*height, tmp->rects[i].y + tmp->rects[i].h);
12731  }
12732  } while ((it = it->n) != config_iter);
12733  }
12734  NK_ASSERT(rect_n == total_glyph_count);
12735  NK_ASSERT(char_n == total_glyph_count);
12736  NK_ASSERT(range_n == total_range_count);
12737  }
12738  *height = (int)nk_round_up_pow2((nk_uint)*height);
12739  *image_memory = (nk_size)(*width) * (nk_size)(*height);
12740  return nk_true;
12741 }
12742 NK_INTERN void
12743 nk_font_bake(struct nk_font_baker *baker, void *image_memory, int width, int height,
12744  struct nk_font_glyph *glyphs, int glyphs_count,
12745  const struct nk_font_config *config_list, int font_count)
12746 {
12747  int input_i = 0;
12748  nk_rune glyph_n = 0;
12749  const struct nk_font_config *config_iter;
12750  const struct nk_font_config *it;
12751 
12752  NK_ASSERT(image_memory);
12753  NK_ASSERT(width);
12754  NK_ASSERT(height);
12755  NK_ASSERT(config_list);
12756  NK_ASSERT(baker);
12757  NK_ASSERT(font_count);
12758  NK_ASSERT(glyphs_count);
12759  if (!image_memory || !width || !height || !config_list ||
12760  !font_count || !glyphs || !glyphs_count)
12761  return;
12762 
12763  /* second font pass: render glyphs */
12764  nk_zero(image_memory, (nk_size)((nk_size)width * (nk_size)height));
12765  baker->spc.pixels = (unsigned char*)image_memory;
12766  baker->spc.height = (int)height;
12767  for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter;
12768  config_iter = config_iter->next) {
12769  it = config_iter;
12770  do {const struct nk_font_config *cfg = it;
12771  struct nk_font_bake_data *tmp = &baker->build[input_i++];
12772  nk_tt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v);
12773  nk_tt_PackFontRangesRenderIntoRects(&baker->spc, &tmp->info, tmp->ranges,
12774  (int)tmp->range_count, tmp->rects, &baker->alloc);
12775  } while ((it = it->n) != config_iter);
12776  } nk_tt_PackEnd(&baker->spc, &baker->alloc);
12777 
12778  /* third pass: setup font and glyphs */
12779  for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter;
12780  config_iter = config_iter->next) {
12781  it = config_iter;
12782  do {nk_size i = 0;
12783  int char_idx = 0;
12784  nk_rune glyph_count = 0;
12785  const struct nk_font_config *cfg = it;
12786  struct nk_font_bake_data *tmp = &baker->build[input_i++];
12787  struct nk_baked_font *dst_font = cfg->font;
12788 
12789  float font_scale = nk_tt_ScaleForPixelHeight(&tmp->info, cfg->size);
12790  int unscaled_ascent, unscaled_descent, unscaled_line_gap;
12791  nk_tt_GetFontVMetrics(&tmp->info, &unscaled_ascent, &unscaled_descent,
12792  &unscaled_line_gap);
12793 
12794  /* fill baked font */
12795  if (!cfg->merge_mode) {
12796  dst_font->ranges = cfg->range;
12797  dst_font->height = cfg->size;
12798  dst_font->ascent = ((float)unscaled_ascent * font_scale);
12799  dst_font->descent = ((float)unscaled_descent * font_scale);
12800  dst_font->glyph_offset = glyph_n;
12801  }
12802 
12803  /* fill own baked font glyph array */
12804  for (i = 0; i < tmp->range_count; ++i) {
12805  struct nk_tt_pack_range *range = &tmp->ranges[i];
12806  for (char_idx = 0; char_idx < range->num_chars; char_idx++)
12807  {
12808  nk_rune codepoint = 0;
12809  float dummy_x = 0, dummy_y = 0;
12810  struct nk_tt_aligned_quad q;
12811  struct nk_font_glyph *glyph;
12812 
12813  /* query glyph bounds from stb_truetype */
12814  const struct nk_tt_packedchar *pc = &range->chardata_for_range[char_idx];
12815  if (!pc->x0 && !pc->x1 && !pc->y0 && !pc->y1) continue;
12816  codepoint = (nk_rune)(range->first_unicode_codepoint_in_range + char_idx);
12817  nk_tt_GetPackedQuad(range->chardata_for_range, (int)width,
12818  (int)height, char_idx, &dummy_x, &dummy_y, &q, 0);
12819 
12820  /* fill own glyph type with data */
12821  glyph = &glyphs[dst_font->glyph_offset + dst_font->glyph_count + (unsigned int)glyph_count];
12822  glyph->codepoint = codepoint;
12823  glyph->x0 = q.x0; glyph->y0 = q.y0;
12824  glyph->x1 = q.x1; glyph->y1 = q.y1;
12825  glyph->y0 += (dst_font->ascent + 0.5f);
12826  glyph->y1 += (dst_font->ascent + 0.5f);
12827  glyph->w = glyph->x1 - glyph->x0 + 0.5f;
12828  glyph->h = glyph->y1 - glyph->y0;
12829 
12830  if (cfg->coord_type == NK_COORD_PIXEL) {
12831  glyph->u0 = q.s0 * (float)width;
12832  glyph->v0 = q.t0 * (float)height;
12833  glyph->u1 = q.s1 * (float)width;
12834  glyph->v1 = q.t1 * (float)height;
12835  } else {
12836  glyph->u0 = q.s0;
12837  glyph->v0 = q.t0;
12838  glyph->u1 = q.s1;
12839  glyph->v1 = q.t1;
12840  }
12841  glyph->xadvance = (pc->xadvance + cfg->spacing.x);
12842  if (cfg->pixel_snap)
12843  glyph->xadvance = (float)(int)(glyph->xadvance + 0.5f);
12844  glyph_count++;
12845  }
12846  }
12847  dst_font->glyph_count += glyph_count;
12848  glyph_n += glyph_count;
12849  } while ((it = it->n) != config_iter);
12850  }
12851 }
12852 NK_INTERN void
12853 nk_font_bake_custom_data(void *img_memory, int img_width, int img_height,
12854  struct nk_recti img_dst, const char *texture_data_mask, int tex_width,
12855  int tex_height, char white, char black)
12856 {
12857  nk_byte *pixels;
12858  int y = 0;
12859  int x = 0;
12860  int n = 0;
12861 
12862  NK_ASSERT(img_memory);
12863  NK_ASSERT(img_width);
12864  NK_ASSERT(img_height);
12865  NK_ASSERT(texture_data_mask);
12866  NK_UNUSED(tex_height);
12867  if (!img_memory || !img_width || !img_height || !texture_data_mask)
12868  return;
12869 
12870  pixels = (nk_byte*)img_memory;
12871  for (y = 0, n = 0; y < tex_height; ++y) {
12872  for (x = 0; x < tex_width; ++x, ++n) {
12873  const int off0 = ((img_dst.x + x) + (img_dst.y + y) * img_width);
12874  const int off1 = off0 + 1 + tex_width;
12875  pixels[off0] = (texture_data_mask[n] == white) ? 0xFF : 0x00;
12876  pixels[off1] = (texture_data_mask[n] == black) ? 0xFF : 0x00;
12877  }
12878  }
12879 }
12880 NK_INTERN void
12881 nk_font_bake_convert(void *out_memory, int img_width, int img_height,
12882  const void *in_memory)
12883 {
12884  int n = 0;
12885  nk_rune *dst;
12886  const nk_byte *src;
12887 
12888  NK_ASSERT(out_memory);
12889  NK_ASSERT(in_memory);
12890  NK_ASSERT(img_width);
12891  NK_ASSERT(img_height);
12892  if (!out_memory || !in_memory || !img_height || !img_width) return;
12893 
12894  dst = (nk_rune*)out_memory;
12895  src = (const nk_byte*)in_memory;
12896  for (n = (int)(img_width * img_height); n > 0; n--)
12897  *dst++ = ((nk_rune)(*src++) << 24) | 0x00FFFFFF;
12898 }
12899 
12900 /* -------------------------------------------------------------
12901  *
12902  * FONT
12903  *
12904  * --------------------------------------------------------------*/
12905 NK_INTERN float
12906 nk_font_text_width(nk_handle handle, float height, const char *text, int len)
12907 {
12908  nk_rune unicode;
12909  int text_len = 0;
12910  float text_width = 0;
12911  int glyph_len = 0;
12912  float scale = 0;
12913 
12914  struct nk_font *font = (struct nk_font*)handle.ptr;
12915  NK_ASSERT(font);
12916  NK_ASSERT(font->glyphs);
12917  if (!font || !text || !len)
12918  return 0;
12919 
12920  scale = height/font->info.height;
12921  glyph_len = text_len = nk_utf_decode(text, &unicode, (int)len);
12922  if (!glyph_len) return 0;
12923  while (text_len <= (int)len && glyph_len) {
12924  const struct nk_font_glyph *g;
12925  if (unicode == NK_UTF_INVALID) break;
12926 
12927  /* query currently drawn glyph information */
12928  g = nk_font_find_glyph(font, unicode);
12929  text_width += g->xadvance * scale;
12930 
12931  /* offset next glyph */
12932  glyph_len = nk_utf_decode(text + text_len, &unicode, (int)len - text_len);
12933  text_len += glyph_len;
12934  }
12935  return text_width;
12936 }
12937 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
12938 NK_INTERN void
12939 nk_font_query_font_glyph(nk_handle handle, float height,
12940  struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint)
12941 {
12942  float scale;
12943  const struct nk_font_glyph *g;
12944  struct nk_font *font;
12945 
12946  NK_ASSERT(glyph);
12947  NK_UNUSED(next_codepoint);
12948 
12949  font = (struct nk_font*)handle.ptr;
12950  NK_ASSERT(font);
12951  NK_ASSERT(font->glyphs);
12952  if (!font || !glyph)
12953  return;
12954 
12955  scale = height/font->info.height;
12956  g = nk_font_find_glyph(font, codepoint);
12957  glyph->width = (g->x1 - g->x0) * scale;
12958  glyph->height = (g->y1 - g->y0) * scale;
12959  glyph->offset = nk_vec2(g->x0 * scale, g->y0 * scale);
12960  glyph->xadvance = (g->xadvance * scale);
12961  glyph->uv[0] = nk_vec2(g->u0, g->v0);
12962  glyph->uv[1] = nk_vec2(g->u1, g->v1);
12963 }
12964 #endif
12965 NK_API const struct nk_font_glyph*
12966 nk_font_find_glyph(struct nk_font *font, nk_rune unicode)
12967 {
12968  int i = 0;
12969  int count;
12970  int total_glyphs = 0;
12971  const struct nk_font_glyph *glyph = 0;
12972  const struct nk_font_config *iter = 0;
12973 
12974  NK_ASSERT(font);
12975  NK_ASSERT(font->glyphs);
12976  NK_ASSERT(font->info.ranges);
12977  if (!font || !font->glyphs) return 0;
12978 
12979  glyph = font->fallback;
12980  iter = font->config;
12981  do {count = nk_range_count(iter->range);
12982  for (i = 0; i < count; ++i) {
12983  nk_rune f = iter->range[(i*2)+0];
12984  nk_rune t = iter->range[(i*2)+1];
12985  int diff = (int)((t - f) + 1);
12986  if (unicode >= f && unicode <= t)
12987  return &font->glyphs[((nk_rune)total_glyphs + (unicode - f))];
12988  total_glyphs += diff;
12989  }
12990  } while ((iter = iter->n) != font->config);
12991  return glyph;
12992 }
12993 NK_INTERN void
12994 nk_font_init(struct nk_font *font, float pixel_height,
12995  nk_rune fallback_codepoint, struct nk_font_glyph *glyphs,
12996  const struct nk_baked_font *baked_font, nk_handle atlas)
12997 {
12998  struct nk_baked_font baked;
12999  NK_ASSERT(font);
13000  NK_ASSERT(glyphs);
13001  NK_ASSERT(baked_font);
13002  if (!font || !glyphs || !baked_font)
13003  return;
13004 
13005  baked = *baked_font;
13006  font->fallback = 0;
13007  font->info = baked;
13008  font->scale = (float)pixel_height / (float)font->info.height;
13009  font->glyphs = &glyphs[baked_font->glyph_offset];
13010  font->texture = atlas;
13011  font->fallback_codepoint = fallback_codepoint;
13012  font->fallback = nk_font_find_glyph(font, fallback_codepoint);
13013 
13014  font->handle.height = font->info.height * font->scale;
13015  font->handle.width = nk_font_text_width;
13016  font->handle.userdata.ptr = font;
13017 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
13018  font->handle.query = nk_font_query_font_glyph;
13019  font->handle.texture = font->texture;
13020 #endif
13021 }
13022 
13023 /* ---------------------------------------------------------------------------
13024  *
13025  * DEFAULT FONT
13026  *
13027  * ProggyClean.ttf
13028  * Copyright (c) 2004, 2005 Tristan Grimmer
13029  * MIT license (see License.txt in http://www.upperbounds.net/download/ProggyClean.ttf.zip)
13030  * Download and more information at http://upperbounds.net
13031  *-----------------------------------------------------------------------------*/
13032 #ifdef NK_INCLUDE_DEFAULT_FONT
13033 
13034  #ifdef __clang__
13035 #pragma clang diagnostic push
13036 
13037 #pragma clang diagnostic ignored "-Woverlength-strings"
13038 #elif defined(__GNUC__) || defined(__GNUG__)
13039 #pragma GCC diagnostic push
13040 #pragma GCC diagnostic ignored "-Woverlength-strings"
13041 #endif
13042 
13043 NK_GLOBAL const char nk_proggy_clean_ttf_compressed_data_base85[11980+1] =
13044  "7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/"
13045  "2*>]b(MC;$jPfY.;h^`IWM9<Lh2TlS+f-s$o6Q<BWH`YiU.xfLq$N;$0iR/GX:U(jcW2p/W*q?-qmnUCI;jHSAiFWM.R*kU@C=GH?a9wp8f$e.-4^Qg1)Q-GL(lf(r/7GrRgwV%MS=C#"
13046  "`8ND>Qo#t'X#(v#Y9w0#1D$CIf;W'#pWUPXOuxXuU(H9M(1<q-UE31#^-V'8IRUo7Qf./L>=Ke$$'5F%)]0^#0X@U.a<r:QLtFsLcL6##lOj)#.Y5<-R&KgLwqJfLgN&;Q?gI^#DY2uL"
13047  "i@^rMl9t=cWq6##weg>$FBjVQTSDgEKnIS7EM9>ZY9w0#L;>>#Mx&4Mvt//L[MkA#W@lK.N'[0#7RL_&#w+F%HtG9M#XL`N&.,GM4Pg;-<nLENhvx>-VsM.M0rJfLH2eTM`*oJMHRC`N"
13048  "kfimM2J,W-jXS:)r0wK#@Fge$U>`w'N7G#$#fB#$E^$#:9:hk+eOe--6x)F7*E%?76%^GMHePW-Z5l'&GiF#$956:rS?dA#fiK:)Yr+`&#0j@'DbG&#^$PG.Ll+DNa<XCMKEV*N)LN/N"
13049  "*b=%Q6pia-Xg8I$<MR&,VdJe$<(7G;Ckl'&hF;;$<_=X(b.RS%%)###MPBuuE1V:v&cX&#2m#(&cV]`k9OhLMbn%s$G2,B$BfD3X*sp5#l,$R#]x_X1xKX%b5U*[r5iMfUo9U`N99hG)"
13050  "tm+/Us9pG)XPu`<0s-)WTt(gCRxIg(%6sfh=ktMKn3j)<6<b5Sk_/0(^]AaN#(p/L>&VZ>1i%h1S9u5o@YaaW$e+b<TWFn/Z:Oh(Cx2$lNEoN^e)#CFY@@I;BOQ*sRwZtZxRcU7uW6CX"
13051  "ow0i(?$Q[cjOd[P4d)]>ROPOpxTO7Stwi1::iB1q)C_=dV26J;2,]7op$]uQr@_V7$q^%lQwtuHY]=DX,n3L#0PHDO4f9>dC@O>HBuKPpP*E,N+b3L#lpR/MrTEH.IAQk.a>D[.e;mc."
13052  "x]Ip.PH^'/aqUO/$1WxLoW0[iLA<QT;5HKD+@qQ'NQ(3_PLhE48R.qAPSwQ0/WK?Z,[x?-J;jQTWA0X@KJ(_Y8N-:/M74:/-ZpKrUss?d#dZq]DAbkU*JqkL+nwX@@47`5>w=4h(9.`G"
13053  "CRUxHPeR`5Mjol(dUWxZa(>STrPkrJiWx`5U7F#.g*jrohGg`cg:lSTvEY/EV_7H4Q9[Z%cnv;JQYZ5q.l7Zeas:HOIZOB?G<Nald$qs]@]L<J7bR*>gv:[7MI2k).'2($5FNP&EQ(,)"
13054  "U]W]+fh18.vsai00);D3@4ku5P?DP8aJt+;qUM]=+b'8@;mViBKx0DE[-auGl8:PJ&Dj+M6OC]O^((##]`0i)drT;-7X`=-H3[igUnPG-NZlo.#k@h#=Ork$m>a>$-?Tm$UV(?#P6YY#"
13055  "'/###xe7q.73rI3*pP/$1>s9)W,JrM7SN]'/4C#v$U`0#V.[0>xQsH$fEmPMgY2u7Kh(G%siIfLSoS+MK2eTM$=5,M8p`A.;_R%#u[K#$x4AG8.kK/HSB==-'Ie/QTtG?-.*^N-4B/ZM"
13056  "_3YlQC7(p7q)&](`6_c)$/*JL(L-^(]$wIM`dPtOdGA,U3:w2M-0<q-]L_?^)1vw'.,MRsqVr.L;aN&#/EgJ)PBc[-f>+WomX2u7lqM2iEumMTcsF?-aT=Z-97UEnXglEn1K-bnEO`gu"
13057  "Ft(c%=;Am_Qs@jLooI&NX;]0#j4#F14;gl8-GQpgwhrq8'=l_f-b49'UOqkLu7-##oDY2L(te+Mch&gLYtJ,MEtJfLh'x'M=$CS-ZZ%P]8bZ>#S?YY#%Q&q'3^Fw&?D)UDNrocM3A76/"
13058  "/oL?#h7gl85[qW/NDOk%16ij;+:1a'iNIdb-ou8.P*w,v5#EI$TWS>Pot-R*H'-SEpA:g)f+O$%%`kA#G=8RMmG1&O`>to8bC]T&$,n.LoO>29sp3dt-52U%VM#q7'DHpg+#Z9%H[K<L"
13059  "%a2E-grWVM3@2=-k22tL]4$##6We'8UJCKE[d_=%wI;'6X-GsLX4j^SgJ$##R*w,vP3wK#iiW&#*h^D&R?jp7+/u&#(AP##XU8c$fSYW-J95_-Dp[g9wcO&#M-h1OcJlc-*vpw0xUX&#"
13060  "OQFKNX@QI'IoPp7nb,QU//MQ&ZDkKP)X<WSVL(68uVl&#c'[0#(s1X&xm$Y%B7*K:eDA323j998GXbA#pwMs-jgD$9QISB-A_(aN4xoFM^@C58D0+Q+q3n0#3U1InDjF682-SjMXJK)("
13061  "h$hxua_K]ul92%'BOU&#BRRh-slg8KDlr:%L71Ka:.A;%YULjDPmL<LYs8i#XwJOYaKPKc1h:'9Ke,g)b),78=I39B;xiY$bgGw-&.Zi9InXDuYa%G*f2Bq7mn9^#p1vv%#(Wi-;/Z5h"
13062  "o;#2:;%d&#x9v68C5g?ntX0X)pT`;%pB3q7mgGN)3%(P8nTd5L7GeA-GL@+%J3u2:(Yf>et`e;)f#Km8&+DC$I46>#Kr]]u-[=99tts1.qb#q72g1WJO81q+eN'03'eM>&1XxY-caEnO"
13063  "j%2n8)),?ILR5^.Ibn<-X-Mq7[a82Lq:F&#ce+S9wsCK*x`569E8ew'He]h:sI[2LM$[guka3ZRd6:t%IG:;$%YiJ:Nq=?eAw;/:nnDq0(CYcMpG)qLN4$##&J<j$UpK<Q4a1]MupW^-"
13064  "sj_$%[HK%'F####QRZJ::Y3EGl4'@%FkiAOg#p[##O`gukTfBHagL<LHw%q&OV0##F=6/:chIm0@eCP8X]:kFI%hl8hgO@RcBhS-@Qb$%+m=hPDLg*%K8ln(wcf3/'DW-$.lR?n[nCH-"
13065  "eXOONTJlh:.RYF%3'p6sq:UIMA945&^HFS87@$EP2iG<-lCO$%c`uKGD3rC$x0BL8aFn--`ke%#HMP'vh1/R&O_J9'um,.<tx[@%wsJk&bUT2`0uMv7gg#qp/ij.L56'hl;.s5CUrxjO"
13066  "M7-##.l+Au'A&O:-T72L]P`&=;ctp'XScX*rU.>-XTt,%OVU4)S1+R-#dg0/Nn?Ku1^0f$B*P:Rowwm-`0PKjYDDM'3]d39VZHEl4,.j']Pk-M.h^&:0FACm$maq-&sgw0t7/6(^xtk%"
13067  "LuH88Fj-ekm>GA#_>568x6(OFRl-IZp`&b,_P'$M<Jnq79VsJW/mWS*PUiq76;]/NM_>hLbxfc$mj`,O;&%W2m`Zh:/)Uetw:aJ%]K9h:TcF]u_-Sj9,VK3M.*'&0D[Ca]J9gp8,kAW]"
13068  "%(?A%R$f<->Zts'^kn=-^@c4%-pY6qI%J%1IGxfLU9CP8cbPlXv);C=b),<2mOvP8up,UVf3839acAWAW-W?#ao/^#%KYo8fRULNd2.>%m]UK:n%r$'sw]J;5pAoO_#2mO3n,'=H5(et"
13069  "Hg*`+RLgv>=4U8guD$I%D:W>-r5V*%j*W:Kvej.Lp$<M-SGZ':+Q_k+uvOSLiEo(<aD/K<CCc`'Lx>'?;++O'>()jLR-^u68PHm8ZFWe+ej8h:9r6L*0//c&iH&R8pRbA#Kjm%upV1g:"
13070  "a_#Ur7FuA#(tRh#.Y5K+@?3<-8m0$PEn;J:rh6?I6uG<-`wMU'ircp0LaE_OtlMb&1#6T.#FDKu#1Lw%u%+GM+X'e?YLfjM[VO0MbuFp7;>Q&#WIo)0@F%q7c#4XAXN-U&VB<HFF*qL("
13071  "$/V,;(kXZejWO`<[5?\?ewY(*9=%wDc;,u<'9t3W-(H1th3+G]ucQ]kLs7df($/*JL]@*t7Bu_G3_7mp7<iaQjO@.kLg;x3B0lqp7Hf,^Ze7-##@/c58Mo(3;knp0%)A7?-W+eI'o8)b<"
13072  "nKnw'Ho8C=Y>pqB>0ie&jhZ[?iLR@@_AvA-iQC(=ksRZRVp7`.=+NpBC%rh&3]R:8XDmE5^V8O(x<<aG/1N$#FX$0V5Y6x'aErI3I$7x%E`v<-BY,)%-?Psf*l?%C3.mM(=/M0:JxG'?"
13073  "7WhH%o'a<-80g0NBxoO(GH<dM]n.+%q@jH?f.UsJ2Ggs&4<-e47&Kl+f//9@`b+?.TeN_&B8Ss?v;^Trk;f#YvJkl&w$]>-+k?'(<S:68tq*WoDfZu';mM?8X[ma8W%*`-=;D.(nc7/;"
13074  ")g:T1=^J$&BRV(-lTmNB6xqB[@0*o.erM*<SWF]u2=st-*(6v>^](H.aREZSi,#1:[IXaZFOm<-ui#qUq2$##Ri;u75OK#(RtaW-K-F`S+cF]uN`-KMQ%rP/Xri.LRcB##=YL3BgM/3M"
13075  "D?@f&1'BW-)Ju<L25gl8uhVm1hL$##*8###'A3/LkKW+(^rWX?5W_8g)a(m&K8P>#bmmWCMkk&#TR`C,5d>g)F;t,4:@_l8G/5h4vUd%&%950:VXD'QdWoY-F$BtUwmfe$YqL'8(PWX("
13076  "P?^@Po3$##`MSs?DWBZ/S>+4%>fX,VWv/w'KD`LP5IbH;rTV>n3cEK8U#bX]l-/V+^lj3;vlMb&[5YQ8#pekX9JP3XUC72L,,?+Ni&co7ApnO*5NK,((W-i:$,kp'UDAO(G0Sq7MVjJs"
13077  "bIu)'Z,*[>br5fX^:FPAWr-m2KgL<LUN098kTF&#lvo58=/vjDo;.;)Ka*hLR#/k=rKbxuV`>Q_nN6'8uTG&#1T5g)uLv:873UpTLgH+#FgpH'_o1780Ph8KmxQJ8#H72L4@768@Tm&Q"
13078  "h4CB/5OvmA&,Q&QbUoi$a_%3M01H)4x7I^&KQVgtFnV+;[Pc>[m4k//,]1?#`VY[Jr*3&&slRfLiVZJ:]?=K3Sw=[$=uRB?3xk48@aeg<Z'<$#4H)6,>e0jT6'N#(q%.O=?2S]u*(m<-"
13079  "V8J'(1)G][68hW$5'q[GC&5j`TE?m'esFGNRM)j,ffZ?-qx8;->g4t*:CIP/[Qap7/9'#(1sao7w-.qNUdkJ)tCF&#B^;xGvn2r9FEPFFFcL@.iFNkTve$m%#QvQS8U@)2Z+3K:AKM5i"
13080  "sZ88+dKQ)W6>J%CL<KE>`.d*(B`-n8D9oK<Up]c$X$(,)M8Zt7/[rdkqTgl-0cuGMv'?>-XV1q['-5k'cAZ69e;D_?$ZPP&s^+7])$*$#@QYi9,5P&#9r+$%CE=68>K8r0=dSC%%(@p7"
13081  ".m7jilQ02'0-VWAg<a/''3u.=4L$Y)6k/K:_[3=&jvL<L0C/2'v:^;-DIBW,B4E68:kZ;%?8(Q8BH=kO65BW?xSG&#@uU,DS*,?.+(o(#1vCS8#CHF>TlGW'b)Tq7VT9q^*^$$.:&N@@"
13082  "$&)WHtPm*5_rO0&e%K&#-30j(E4#'Zb.o/(Tpm$>K'f@[PvFl,hfINTNU6u'0pao7%XUp9]5.>%h`8_=VYbxuel.NTSsJfLacFu3B'lQSu/m6-Oqem8T+oE--$0a/k]uj9EwsG>%veR*"
13083  "hv^BFpQj:K'#SJ,sB-'#](j.Lg92rTw-*n%@/;39rrJF,l#qV%OrtBeC6/,;qB3ebNW[?,Hqj2L.1NP&GjUR=1D8QaS3Up&@*9wP?+lo7b?@%'k4`p0Z$22%K3+iCZj?XJN4Nm&+YF]u"
13084  "@-W$U%VEQ/,,>>#)D<h#`)h0:<Q6909ua+&VU%n2:cG3FJ-%@Bj-DgLr`Hw&HAKjKjseK</xKT*)B,N9X3]krc12t'pgTV(Lv-tL[xg_%=M_q7a^x?7Ubd>#%8cY#YZ?=,`Wdxu/ae&#"
13085  "w6)R89tI#6@s'(6Bf7a&?S=^ZI_kS&ai`&=tE72L_D,;^R)7[$s<Eh#c&)q.MXI%#v9ROa5FZO%sF7q7Nwb&#ptUJ:aqJe$Sl68%.D###EC><?-aF&#RNQv>o8lKN%5/$(vdfq7+ebA#"
13086  "u1p]ovUKW&Y%q]'>$1@-[xfn$7ZTp7mM,G,Ko7a&Gu%G[RMxJs[0MM%wci.LFDK)(<c`Q8N)jEIF*+?P2a8g%)$q]o2aH8C&<SibC/q,(e:v;-b#6[$NtDZ84Je2KNvB#$P5?tQ3nt(0"
13087  "d=j.LQf./Ll33+(;q3L-w=8dX$#WF&uIJ@-bfI>%:_i2B5CsR8&9Z&#=mPEnm0f`<&c)QL5uJ#%u%lJj+D-r;BoF&#4DoS97h5g)E#o:&S4weDF,9^Hoe`h*L+_a*NrLW-1pG_&2UdB8"
13088  "6e%B/:=>)N4xeW.*wft-;$'58-ESqr<b?UI(_%@[P46>#U`'6AQ]m&6/`Z>#S?YY#Vc;r7U2&326d=w&H####?TZ`*4?&.MK?LP8Vxg>$[QXc%QJv92.(Db*B)gb*BM9dM*hJMAo*c&#"
13089  "b0v=Pjer]$gG&JXDf->'StvU7505l9$AFvgYRI^&<^b68?j#q9QX4SM'RO#&sL1IM.rJfLUAj221]d##DW=m83u5;'bYx,*Sl0hL(W;;$doB&O/TQ:(Z^xBdLjL<Lni;''X.`$#8+1GD"
13090  ":k$YUWsbn8ogh6rxZ2Z9]%nd+>V#*8U_72Lh+2Q8Cj0i:6hp&$C/:p(HK>T8Y[gHQ4`4)'$Ab(Nof%V'8hL&#<NEdtg(n'=S1A(Q1/I&4([%dM`,Iu'1:_hL>SfD07&6D<fp8dHM7/g+"
13091  "tlPN9J*rKaPct&?'uBCem^jn%9_K)<,C5K3s=5g&GmJb*[SYq7K;TRLGCsM-$$;S%:Y@r7AK0pprpL<Lrh,q7e/%KWK:50I^+m'vi`3?%Zp+<-d+$L-Sv:@.o19n$s0&39;kn;S%BSq*"
13092  "$3WoJSCLweV[aZ'MQIjO<7;X-X;&+dMLvu#^UsGEC9WEc[X(wI7#2.(F0jV*eZf<-Qv3J-c+J5AlrB#$p(H68LvEA'q3n0#m,[`*8Ft)FcYgEud]CWfm68,(aLA$@EFTgLXoBq/UPlp7"
13093  ":d[/;r_ix=:TF`S5H-b<LI&HY(K=h#)]Lk$K14lVfm:x$H<3^Ql<M`$OhapBnkup'D#L$Pb_`N*g]2e;X/Dtg,bsj&K#2[-:iYr'_wgH)NUIR8a1n#S?Yej'h8^58UbZd+^FKD*T@;6A"
13094  "7aQC[K8d-(v6GI$x:T<&'Gp5Uf>@M.*J:;$-rv29'M]8qMv-tLp,'886iaC=Hb*YJoKJ,(j%K=H`K.v9HggqBIiZu'QvBT.#=)0ukruV&.)3=(^1`o*Pj4<-<aN((^7('#Z0wK#5GX@7"
13095  "u][`*S^43933A4rl][`*O4CgLEl]v$1Q3AeF37dbXk,.)vj#x'd`;qgbQR%FW,2(?LO=s%Sc68%NP'##Aotl8x=BE#j1UD([3$M(]UI2LX3RpKN@;/#f'f/&_mt&F)XdF<9t4)Qa.*kT"
13096  "LwQ'(TTB9.xH'>#MJ+gLq9-##@HuZPN0]u:h7.T..G:;$/Usj(T7`Q8tT72LnYl<-qx8;-HV7Q-&Xdx%1a,hC=0u+HlsV>nuIQL-5<N?)NBS)QN*_I,?&)2'IM%L3I)X((e/dl2&8'<M"
13097  ":^#M*Q+[T.Xri.LYS3v%fF`68h;b-X[/En'CR.q7E)p'/kle2HM,u;^%OKC-N+Ll%F9CF<Nf'^#t2L,;27W:0O@6##U6W7:$rJfLWHj$#)woqBefIZ.PK<b*t7ed;p*_m;4ExK#h@&]>"
13098  "_>@kXQtMacfD.m-VAb8;IReM3$wf0''hra*so568'Ip&vRs849'MRYSp%:t:h5qSgwpEr$B>Q,;s(C#$)`svQuF$##-D,##,g68@2[T;.XSdN9Qe)rpt._K-#5wF)sP'##p#C0c%-Gb%"
13099  "hd+<-j'Ai*x&&HMkT]C'OSl##5RG[JXaHN;d'uA#x._U;.`PU@(Z3dt4r152@:v,'R.Sj'w#0<-;kPI)FfJ&#AYJ&#//)>-k=m=*XnK$>=)72L]0I%>.G690a:$##<,);?;72#?x9+d;"
13100  "^V'9;jY@;)br#q^YQpx:X#Te$Z^'=-=bGhLf:D6&bNwZ9-ZD#n^9HhLMr5G;']d&6'wYmTFmL<LD)F^%[tC'8;+9E#C$g%#5Y>q9wI>P(9mI[>kC-ekLC/R&CH+s'B;K-M6$EB%is00:"
13101  "+A4[7xks.LrNk0&E)wILYF@2L'0Nb$+pv<(2.768/FrY&h$^3i&@+G%JT'<-,v`3;_)I9M^AE]CN?Cl2AZg+%4iTpT3<n-&%H%b<FDj2M<hH=&Eh<2Len$b*aTX=-8QxN)k11IM1c^j%"
13102  "9s<L<NFSo)B?+<-(GxsF,^-Eh@$4dXhN$+#rxK8'je'D7k`e;)2pYwPA'_p9&@^18ml1^[@g4t*[JOa*[=Qp7(qJ_oOL^('7fB&Hq-:sf,sNj8xq^>$U4O]GKx'm9)b@p7YsvK3w^YR-"
13103  "CdQ*:Ir<($u&)#(&?L9Rg3H)4fiEp^iI9O8KnTj,]H?D*r7'M;PwZ9K0E^k&-cpI;.p/6_vwoFMV<->#%Xi.LxVnrU(4&8/P+:hLSKj$#U%]49t'I:rgMi'FL@a:0Y-uA[39',(vbma*"
13104  "hU%<-SRF`Tt:542R_VV$p@[p8DV[A,?1839FWdF<TddF<9Ah-6&9tWoDlh]&1SpGMq>Ti1O*H&#(AL8[_P%.M>v^-))qOT*F5Cq0`Ye%+$B6i:7@0IX<N+T+0MlMBPQ*Vj>SsD<U4JHY"
13105  "8kD2)2fU/M#$e.)T4,_=8hLim[&);?UkK'-x?'(:siIfL<$pFM`i<?%W(mGDHM%>iWP,##P`%/L<eXi:@Z9C.7o=@(pXdAO/NLQ8lPl+HPOQa8wD8=^GlPa8TKI1CjhsCTSLJM'/Wl>-"
13106  "S(qw%sf/@%#B6;/U7K]uZbi^Oc^2n<bhPmUkMw>%t<)'mEVE''n`WnJra$^TKvX5B>;_aSEK',(hwa0:i4G?.Bci.(X[?b*($,=-n<.Q%`(X=?+@Am*Js0&=3bh8K]mL<LoNs'6,'85`"
13107  "0?t/'_U59@]ddF<#LdF<eWdF<OuN/45rY<-L@&#+fm>69=Lb,OcZV/);TTm8VI;?%OtJ<(b4mq7M6:u?KRdF<gR@2L=FNU-<b[(9c/ML3m;Z[$oF3g)GAWqpARc=<ROu7cL5l;-[A]%/"
13108  "+fsd;l#SafT/f*W]0=O'$(Tb<[)*@e775R-:Yob%g*>l*:xP?Yb.5)%w_I?7uk5JC+FS(m#i'k.'a0i)9<7b'fs'59hq$*5Uhv##pi^8+hIEBF`nvo`;'l0.^S1<-wUK2/Coh58KKhLj"
13109  "M=SO*rfO`+qC`W-On.=AJ56>>i2@2LH6A:&5q`?9I3@@'04&p2/LVa*T-4<-i3;M9UvZd+N7>b*eIwg:CC)c<>nO&#<IGe;__.thjZl<%w(Wk2xmp4Q@I#I9,DF]u7-P=.-_:YJ]aS@V"
13110  "?6*C()dOp7:WL,b&3Rg/.cmM9&r^>$(>.Z-I&J(Q0Hd5Q%7Co-b`-c<N(6r@ip+AurK<m86QIth*#v;-OBqi+L7wDE-Ir8K['m+DDSLwK&/.?-V%U_%3:qKNu$_b*B-kp7NaD'QdWQPK"
13111  "Yq[@>P)hI;*_F]u`Rb[.j8_Q/<&>uu+VsH$sM9TA%?)(vmJ80),P7E>)tjD%2L=-t#fK[%`v=Q8<FfNkgg^oIbah*#8/Qt$F&:K*-(N/'+1vMB,u()-a.VUU*#[e%gAAO(S>WlA2);Sa"
13112  ">gXm8YB`1d@K#n]76-a$U,mF<fX]idqd)<3,]J7JmW4`6]uks=4-72L(jEk+:bJ0M^q-8Dm_Z?0olP1C9Sa&H[d&c$ooQUj]Exd*3ZM@-WGW2%s',B-_M%>%Ul:#/'xoFM9QX-$.QN'>"
13113  "[%$Z$uF6pA6Ki2O5:8w*vP1<-1`[G,)-m#>0`P&#eb#.3i)rtB61(o'$?X3B</R90;eZ]%Ncq;-Tl]#F>2Qft^ae_5tKL9MUe9b*sLEQ95C&`=G?@Mj=wh*'3E>=-<)Gt*Iw)'QG:`@I"
13114  "wOf7&]1i'S01B+Ev/Nac#9S;=;YQpg_6U`*kVY39xK,[/6Aj7:'1Bm-_1EYfa1+o&o4hp7KN_Q(OlIo@S%;jVdn0'1<Vc52=u`3^o-n1'g4v58Hj&6_t7$##?M)c<$bgQ_'SY((-xkA#"
13115  "Y(,p'H9rIVY-b,'%bCPF7.J<Up^,(dU1VY*5#WkTU>h19w,WQhLI)3S#f$2(eb,jr*b;3Vw]*7NH%$c4Vs,eD9>XW8?N]o+(*pgC%/72LV-u<Hp,3@e^9UB1J+ak9-TN/mhKPg+AJYd$"
13116  "MlvAF_jCK*.O-^(63adMT->W%iewS8W6m2rtCpo'RS1R84=@paTKt)>=%&1[)*vp'u+x,VrwN;&]kuO9JDbg=pO$J*.jVe;u'm0dr9l,<*wMK*Oe=g8lV_KEBFkO'oU]^=[-792#ok,)"
13117  "i]lR8qQ2oA8wcRCZ^7w/Njh;?.stX?Q1>S1q4Bn$)K1<-rGdO'$Wr.Lc.CG)$/*JL4tNR/,SVO3,aUw'DJN:)Ss;wGn9A32ijw%FL+Z0Fn.U9;reSq)bmI32U==5ALuG&#Vf1398/pVo"
13118  "1*c-(aY168o<`JsSbk-,1N;$>0:OUas(3:8Z972LSfF8eb=c-;>SPw7.6hn3m`9^Xkn(r.qS[0;T%&Qc=+STRxX'q1BNk3&*eu2;&8q$&x>Q#Q7^Tf+6<(d%ZVmj2bDi%.3L2n+4W'$P"
13119  "iDDG)g,r%+?,$@?uou5tSe2aN_AQU*<h`e-GI7)?OK2A.d7_c)?wQ5AS@DL3r#7fSkgl6-++D:'A,uq7SvlB$pcpH'q3n0#_%dY#xCpr-l<F0NR@-##FEV6NTF6##$l84N1w?AO>'IAO"
13120  "URQ##V^Fv-XFbGM7Fl(N<3DhLGF%q.1rC$#:T__&Pi68%0xi_&[qFJ(77j_&JWoF.V735&T,[R*:xFR*K5>>#`bW-?4Ne_&6Ne_&6Ne_&n`kr-#GJcM6X;uM6X;uM(.a..^2TkL%oR(#"
13121  ";u.T%fAr%4tJ8&><1=GHZ_+m9/#H1F^R#SC#*N=BA9(D?v[UiFY>>^8p,KKF.W]L29uLkLlu/+4T<XoIB&hx=T1PcDaB&;HH+-AFr?(m9HZV)FKS8JCw;SD=6[^/DZUL`EUDf]GGlG&>"
13122  "w$)F./^n3+rlo+DB;5sIYGNk+i1t-69Jg--0pao7Sm#K)pdHW&;LuDNH@H>#/X-TI(;P>#,Gc>#0Su>#4`1?#8lC?#<xU?#@.i?#D:%@#HF7@#LRI@#P_[@#Tkn@#Xw*A#]-=A#a9OA#"
13123  "d<F&#*;G##.GY##2Sl##6`($#:l:$#>xL$#B.`$#F:r$#JF.%#NR@%#R_R%#Vke%#Zww%#_-4&#3^Rh%Sflr-k'MS.o?.5/sWel/wpEM0%3'/1)K^f1-d>G21&v(35>V`39V7A4=onx4"
13124  "A1OY5EI0;6Ibgr6M$HS7Q<)58C5w,;WoA*#[%T*#`1g*#d=#+#hI5+#lUG+#pbY+#tnl+#x$),#&1;,#*=M,#.I`,#2Ur,#6b.-#;w[H#iQtA#m^0B#qjBB#uvTB##-hB#'9$C#+E6C#"
13125  "/QHC#3^ZC#7jmC#;v)D#?,<D#C8ND#GDaD#KPsD#O]/E#g1A5#KA*1#gC17#MGd;#8(02#L-d3#rWM4#Hga1#,<w0#T.j<#O#'2#CYN1#qa^:#_4m3#o@/=#eG8=#t8J5#`+78#4uI-#"
13126  "m3B2#SB[8#Q0@8#i[*9#iOn8#1Nm;#^sN9#qh<9#:=x-#P;K2#$%X9#bC+.#Rg;<#mN=.#MTF.#RZO.#2?)4#Y#(/#[)1/#b;L/#dAU/#0Sv;#lY$0#n`-0#sf60#(F24#wrH0#%/e0#"
13127  "TmD<#%JSMFove:CTBEXI:<eh2g)B,3h2^G3i;#d3jD>)4kMYD4lVu`4m`:&5niUA5@(A5BA1]PBB:xlBCC=2CDLXMCEUtiCf&0g2'tN?PGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CP"
13128  "GT4CPGT4CPGT4CPGT4CPGT4CPGT4CP-qekC`.9kEg^+F$kwViFJTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5o,^<-28ZI'O?;xp"
13129  "O?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xp;7q-#lLYI:xvD=#";
13130 #endif /* NK_INCLUDE_DEFAULT_FONT */
13131 
13132 #define NK_CURSOR_DATA_W 90
13133 #define NK_CURSOR_DATA_H 27
13134 NK_GLOBAL const char nk_custom_cursor_data[NK_CURSOR_DATA_W * NK_CURSOR_DATA_H + 1] =
13135 {
13136  "..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX"
13137  "..- -X.....X- X.X - X.X -X.....X - X.....X"
13138  "--- -XXX.XXX- X...X - X...X -X....X - X....X"
13139  "X - X.X - X.....X - X.....X -X...X - X...X"
13140  "XX - X.X -X.......X- X.......X -X..X.X - X.X..X"
13141  "X.X - X.X -XXXX.XXXX- XXXX.XXXX -X.X X.X - X.X X.X"
13142  "X..X - X.X - X.X - X.X -XX X.X - X.X XX"
13143  "X...X - X.X - X.X - XX X.X XX - X.X - X.X "
13144  "X....X - X.X - X.X - X.X X.X X.X - X.X - X.X "
13145  "X.....X - X.X - X.X - X..X X.X X..X - X.X - X.X "
13146  "X......X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X XX-XX X.X "
13147  "X.......X - X.X - X.X -X.....................X- X.X X.X-X.X X.X "
13148  "X........X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X..X-X..X.X "
13149  "X.........X -XXX.XXX- X.X - X..X X.X X..X - X...X-X...X "
13150  "X..........X-X.....X- X.X - X.X X.X X.X - X....X-X....X "
13151  "X......XXXXX-XXXXXXX- X.X - XX X.X XX - X.....X-X.....X "
13152  "X...X..X --------- X.X - X.X - XXXXXXX-XXXXXXX "
13153  "X..X X..X - -XXXX.XXXX- XXXX.XXXX ------------------------------------"
13154  "X.X X..X - -X.......X- X.......X - XX XX - "
13155  "XX X..X - - X.....X - X.....X - X.X X.X - "
13156  " X..X - X...X - X...X - X..X X..X - "
13157  " XX - X.X - X.X - X...XXXXXXXXXXXXX...X - "
13158  "------------ - X - X -X.....................X- "
13159  " ----------------------------------- X...XXXXXXXXXXXXX...X - "
13160  " - X..X X..X - "
13161  " - X.X X.X - "
13162  " - XX XX - "
13163 };
13164 
13165 #ifdef __clang__
13166 #pragma clang diagnostic pop
13167 #elif defined(__GNUC__) || defined(__GNUG__)
13168 #pragma GCC diagnostic pop
13169 #endif
13170 
13171 NK_GLOBAL unsigned char *nk__barrier;
13172 NK_GLOBAL unsigned char *nk__barrier2;
13173 NK_GLOBAL unsigned char *nk__barrier3;
13174 NK_GLOBAL unsigned char *nk__barrier4;
13175 NK_GLOBAL unsigned char *nk__dout;
13176 
13177 NK_INTERN unsigned int
13178 nk_decompress_length(unsigned char *input)
13179 {
13180  return (unsigned int)((input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11]);
13181 }
13182 NK_INTERN void
13183 nk__match(unsigned char *data, unsigned int length)
13184 {
13185  /* INVERSE of memmove... write each byte before copying the next...*/
13186  NK_ASSERT (nk__dout + length <= nk__barrier);
13187  if (nk__dout + length > nk__barrier) { nk__dout += length; return; }
13188  if (data < nk__barrier4) { nk__dout = nk__barrier+1; return; }
13189  while (length--) *nk__dout++ = *data++;
13190 }
13191 NK_INTERN void
13192 nk__lit(unsigned char *data, unsigned int length)
13193 {
13194  NK_ASSERT (nk__dout + length <= nk__barrier);
13195  if (nk__dout + length > nk__barrier) { nk__dout += length; return; }
13196  if (data < nk__barrier2) { nk__dout = nk__barrier+1; return; }
13197  NK_MEMCPY(nk__dout, data, length);
13198  nk__dout += length;
13199 }
13200 NK_INTERN unsigned char*
13201 nk_decompress_token(unsigned char *i)
13202 {
13203  #define nk__in2(x) ((i[x] << 8) + i[(x)+1])
13204  #define nk__in3(x) ((i[x] << 16) + nk__in2((x)+1))
13205  #define nk__in4(x) ((i[x] << 24) + nk__in3((x)+1))
13206 
13207  if (*i >= 0x20) { /* use fewer if's for cases that expand small */
13208  if (*i >= 0x80) nk__match(nk__dout-i[1]-1, (unsigned int)i[0] - 0x80 + 1), i += 2;
13209  else if (*i >= 0x40) nk__match(nk__dout-(nk__in2(0) - 0x4000 + 1), (unsigned int)i[2]+1), i += 3;
13210  else /* *i >= 0x20 */ nk__lit(i+1, (unsigned int)i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1);
13211  } else { /* more ifs for cases that expand large, since overhead is amortized */
13212  if (*i >= 0x18) nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x180000 + 1), (unsigned int)i[3]+1), i += 4;
13213  else if (*i >= 0x10) nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x100000 + 1), (unsigned int)nk__in2(3)+1), i += 5;
13214  else if (*i >= 0x08) nk__lit(i+2, (unsigned int)nk__in2(0) - 0x0800 + 1), i += 2 + (nk__in2(0) - 0x0800 + 1);
13215  else if (*i == 0x07) nk__lit(i+3, (unsigned int)nk__in2(1) + 1), i += 3 + (nk__in2(1) + 1);
13216  else if (*i == 0x06) nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), i[4]+1u), i += 5;
13217  else if (*i == 0x04) nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), (unsigned int)nk__in2(4)+1u), i += 6;
13218  }
13219  return i;
13220 }
13221 NK_INTERN unsigned int
13222 nk_adler32(unsigned int adler32, unsigned char *buffer, unsigned int buflen)
13223 {
13224  const unsigned long ADLER_MOD = 65521;
13225  unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16;
13226  unsigned long blocklen, i;
13227 
13228  blocklen = buflen % 5552;
13229  while (buflen) {
13230  for (i=0; i + 7 < blocklen; i += 8) {
13231  s1 += buffer[0]; s2 += s1;
13232  s1 += buffer[1]; s2 += s1;
13233  s1 += buffer[2]; s2 += s1;
13234  s1 += buffer[3]; s2 += s1;
13235  s1 += buffer[4]; s2 += s1;
13236  s1 += buffer[5]; s2 += s1;
13237  s1 += buffer[6]; s2 += s1;
13238  s1 += buffer[7]; s2 += s1;
13239  buffer += 8;
13240  }
13241  for (; i < blocklen; ++i) {
13242  s1 += *buffer++; s2 += s1;
13243  }
13244 
13245  s1 %= ADLER_MOD; s2 %= ADLER_MOD;
13246  buflen -= (unsigned int)blocklen;
13247  blocklen = 5552;
13248  }
13249  return (unsigned int)(s2 << 16) + (unsigned int)s1;
13250 }
13251 NK_INTERN unsigned int
13252 nk_decompress(unsigned char *output, unsigned char *i, unsigned int length)
13253 {
13254  unsigned int olen;
13255  if (nk__in4(0) != 0x57bC0000) return 0;
13256  if (nk__in4(4) != 0) return 0; /* error! stream is > 4GB */
13257  olen = nk_decompress_length(i);
13258  nk__barrier2 = i;
13259  nk__barrier3 = i+length;
13260  nk__barrier = output + olen;
13261  nk__barrier4 = output;
13262  i += 16;
13263 
13264  nk__dout = output;
13265  for (;;) {
13266  unsigned char *old_i = i;
13267  i = nk_decompress_token(i);
13268  if (i == old_i) {
13269  if (*i == 0x05 && i[1] == 0xfa) {
13270  NK_ASSERT(nk__dout == output + olen);
13271  if (nk__dout != output + olen) return 0;
13272  if (nk_adler32(1, output, olen) != (unsigned int) nk__in4(2))
13273  return 0;
13274  return olen;
13275  } else {
13276  NK_ASSERT(0); /* NOTREACHED */
13277  return 0;
13278  }
13279  }
13280  NK_ASSERT(nk__dout <= output + olen);
13281  if (nk__dout > output + olen)
13282  return 0;
13283  }
13284 }
13285 NK_INTERN unsigned int
13286 nk_decode_85_byte(char c)
13287 {
13288  return (unsigned int)((c >= '\\') ? c-36 : c-35);
13289 }
13290 NK_INTERN void
13291 nk_decode_85(unsigned char* dst, const unsigned char* src)
13292 {
13293  while (*src)
13294  {
13295  unsigned int tmp =
13296  nk_decode_85_byte((char)src[0]) +
13297  85 * (nk_decode_85_byte((char)src[1]) +
13298  85 * (nk_decode_85_byte((char)src[2]) +
13299  85 * (nk_decode_85_byte((char)src[3]) +
13300  85 * nk_decode_85_byte((char)src[4]))));
13301 
13302  /* we can't assume little-endianess. */
13303  dst[0] = (unsigned char)((tmp >> 0) & 0xFF);
13304  dst[1] = (unsigned char)((tmp >> 8) & 0xFF);
13305  dst[2] = (unsigned char)((tmp >> 16) & 0xFF);
13306  dst[3] = (unsigned char)((tmp >> 24) & 0xFF);
13307 
13308  src += 5;
13309  dst += 4;
13310  }
13311 }
13312 
13313 /* -------------------------------------------------------------
13314  *
13315  * FONT ATLAS
13316  *
13317  * --------------------------------------------------------------*/
13318 NK_API struct nk_font_config
13319 nk_font_config(float pixel_height)
13320 {
13321  struct nk_font_config cfg;
13322  nk_zero_struct(cfg);
13323  cfg.ttf_blob = 0;
13324  cfg.ttf_size = 0;
13325  cfg.ttf_data_owned_by_atlas = 0;
13326  cfg.size = pixel_height;
13327  cfg.oversample_h = 3;
13328  cfg.oversample_v = 1;
13329  cfg.pixel_snap = 0;
13330  cfg.coord_type = NK_COORD_UV;
13331  cfg.spacing = nk_vec2(0,0);
13332  cfg.range = nk_font_default_glyph_ranges();
13333  cfg.merge_mode = 0;
13334  cfg.fallback_glyph = '?';
13335  cfg.font = 0;
13336  cfg.n = 0;
13337  return cfg;
13338 }
13339 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
13340 NK_API void
13341 nk_font_atlas_init_default(struct nk_font_atlas *atlas)
13342 {
13343  NK_ASSERT(atlas);
13344  if (!atlas) return;
13345  nk_zero_struct(*atlas);
13346  atlas->temporary.userdata.ptr = 0;
13347  atlas->temporary.alloc = nk_malloc;
13348  atlas->temporary.free = nk_mfree;
13349  atlas->permanent.userdata.ptr = 0;
13350  atlas->permanent.alloc = nk_malloc;
13351  atlas->permanent.free = nk_mfree;
13352 }
13353 #endif
13354 NK_API void
13355 nk_font_atlas_init(struct nk_font_atlas *atlas, struct nk_allocator *alloc)
13356 {
13357  NK_ASSERT(atlas);
13358  NK_ASSERT(alloc);
13359  if (!atlas || !alloc) return;
13360  nk_zero_struct(*atlas);
13361  atlas->permanent = *alloc;
13362  atlas->temporary = *alloc;
13363 }
13364 NK_API void
13365 nk_font_atlas_init_custom(struct nk_font_atlas *atlas,
13366  struct nk_allocator *permanent, struct nk_allocator *temporary)
13367 {
13368  NK_ASSERT(atlas);
13369  NK_ASSERT(permanent);
13370  NK_ASSERT(temporary);
13371  if (!atlas || !permanent || !temporary) return;
13372  nk_zero_struct(*atlas);
13373  atlas->permanent = *permanent;
13374  atlas->temporary = *temporary;
13375 }
13376 NK_API void
13377 nk_font_atlas_begin(struct nk_font_atlas *atlas)
13378 {
13379  NK_ASSERT(atlas);
13380  NK_ASSERT(atlas->temporary.alloc && atlas->temporary.free);
13381  NK_ASSERT(atlas->permanent.alloc && atlas->permanent.free);
13382  if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free ||
13383  !atlas->temporary.alloc || !atlas->temporary.free) return;
13384  if (atlas->glyphs) {
13385  atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
13386  atlas->glyphs = 0;
13387  }
13388  if (atlas->pixel) {
13389  atlas->permanent.free(atlas->permanent.userdata, atlas->pixel);
13390  atlas->pixel = 0;
13391  }
13392 }
13393 NK_API struct nk_font*
13394 nk_font_atlas_add(struct nk_font_atlas *atlas, const struct nk_font_config *config)
13395 {
13396  struct nk_font *font = 0;
13397  struct nk_font_config *cfg;
13398 
13399  NK_ASSERT(atlas);
13400  NK_ASSERT(atlas->permanent.alloc);
13401  NK_ASSERT(atlas->permanent.free);
13402  NK_ASSERT(atlas->temporary.alloc);
13403  NK_ASSERT(atlas->temporary.free);
13404 
13405  NK_ASSERT(config);
13406  NK_ASSERT(config->ttf_blob);
13407  NK_ASSERT(config->ttf_size);
13408  NK_ASSERT(config->size > 0.0f);
13409 
13410  if (!atlas || !config || !config->ttf_blob || !config->ttf_size || config->size <= 0.0f||
13411  !atlas->permanent.alloc || !atlas->permanent.free ||
13412  !atlas->temporary.alloc || !atlas->temporary.free)
13413  return 0;
13414 
13415  /* allocate font config */
13416  cfg = (struct nk_font_config*)
13417  atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font_config));
13418  NK_MEMCPY(cfg, config, sizeof(*config));
13419  cfg->n = cfg;
13420  cfg->p = cfg;
13421 
13422  if (!config->merge_mode) {
13423  /* insert font config into list */
13424  if (!atlas->config) {
13425  atlas->config = cfg;
13426  cfg->next = 0;
13427  } else {
13428  struct nk_font_config *i = atlas->config;
13429  while (i->next) i = i->next;
13430  i->next = cfg;
13431  cfg->next = 0;
13432  }
13433  /* allocate new font */
13434  font = (struct nk_font*)
13435  atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font));
13436  NK_ASSERT(font);
13437  nk_zero(font, sizeof(*font));
13438  if (!font) return 0;
13439  font->config = cfg;
13440 
13441  /* insert font into list */
13442  if (!atlas->fonts) {
13443  atlas->fonts = font;
13444  font->next = 0;
13445  } else {
13446  struct nk_font *i = atlas->fonts;
13447  while (i->next) i = i->next;
13448  i->next = font;
13449  font->next = 0;
13450  }
13451  cfg->font = &font->info;
13452  } else {
13453  /* extend previously added font */
13454  struct nk_font *f = 0;
13455  struct nk_font_config *c = 0;
13456  NK_ASSERT(atlas->font_num);
13457  f = atlas->fonts;
13458  c = f->config;
13459  cfg->font = &f->info;
13460 
13461  cfg->n = c;
13462  cfg->p = c->p;
13463  c->p->n = cfg;
13464  c->p = cfg;
13465  }
13466  /* create own copy of .TTF font blob */
13467  if (!config->ttf_data_owned_by_atlas) {
13468  cfg->ttf_blob = atlas->permanent.alloc(atlas->permanent.userdata,0, cfg->ttf_size);
13469  NK_ASSERT(cfg->ttf_blob);
13470  if (!cfg->ttf_blob) {
13471  atlas->font_num++;
13472  return 0;
13473  }
13474  NK_MEMCPY(cfg->ttf_blob, config->ttf_blob, cfg->ttf_size);
13475  cfg->ttf_data_owned_by_atlas = 1;
13476  }
13477  atlas->font_num++;
13478  return font;
13479 }
13480 NK_API struct nk_font*
13481 nk_font_atlas_add_from_memory(struct nk_font_atlas *atlas, void *memory,
13482  nk_size size, float height, const struct nk_font_config *config)
13483 {
13484  struct nk_font_config cfg;
13485  NK_ASSERT(memory);
13486  NK_ASSERT(size);
13487 
13488  NK_ASSERT(atlas);
13489  NK_ASSERT(atlas->temporary.alloc);
13490  NK_ASSERT(atlas->temporary.free);
13491  NK_ASSERT(atlas->permanent.alloc);
13492  NK_ASSERT(atlas->permanent.free);
13493  if (!atlas || !atlas->temporary.alloc || !atlas->temporary.free || !memory || !size ||
13494  !atlas->permanent.alloc || !atlas->permanent.free)
13495  return 0;
13496 
13497  cfg = (config) ? *config: nk_font_config(height);
13498  cfg.ttf_blob = memory;
13499  cfg.ttf_size = size;
13500  cfg.size = height;
13501  cfg.ttf_data_owned_by_atlas = 0;
13502  return nk_font_atlas_add(atlas, &cfg);
13503 }
13504 #ifdef NK_INCLUDE_STANDARD_IO
13505 NK_API struct nk_font*
13506 nk_font_atlas_add_from_file(struct nk_font_atlas *atlas, const char *file_path,
13507  float height, const struct nk_font_config *config)
13508 {
13509  nk_size size;
13510  char *memory;
13511  struct nk_font_config cfg;
13512 
13513  NK_ASSERT(atlas);
13514  NK_ASSERT(atlas->temporary.alloc);
13515  NK_ASSERT(atlas->temporary.free);
13516  NK_ASSERT(atlas->permanent.alloc);
13517  NK_ASSERT(atlas->permanent.free);
13518 
13519  if (!atlas || !file_path) return 0;
13520  memory = nk_file_load(file_path, &size, &atlas->permanent);
13521  if (!memory) return 0;
13522 
13523  cfg = (config) ? *config: nk_font_config(height);
13524  cfg.ttf_blob = memory;
13525  cfg.ttf_size = size;
13526  cfg.size = height;
13527  cfg.ttf_data_owned_by_atlas = 1;
13528  return nk_font_atlas_add(atlas, &cfg);
13529 }
13530 #endif
13531 NK_API struct nk_font*
13532 nk_font_atlas_add_compressed(struct nk_font_atlas *atlas,
13533  void *compressed_data, nk_size compressed_size, float height,
13534  const struct nk_font_config *config)
13535 {
13536  unsigned int decompressed_size;
13537  void *decompressed_data;
13538  struct nk_font_config cfg;
13539 
13540  NK_ASSERT(atlas);
13541  NK_ASSERT(atlas->temporary.alloc);
13542  NK_ASSERT(atlas->temporary.free);
13543  NK_ASSERT(atlas->permanent.alloc);
13544  NK_ASSERT(atlas->permanent.free);
13545 
13546  NK_ASSERT(compressed_data);
13547  NK_ASSERT(compressed_size);
13548  if (!atlas || !compressed_data || !atlas->temporary.alloc || !atlas->temporary.free ||
13549  !atlas->permanent.alloc || !atlas->permanent.free)
13550  return 0;
13551 
13552  decompressed_size = nk_decompress_length((unsigned char*)compressed_data);
13553  decompressed_data = atlas->permanent.alloc(atlas->permanent.userdata,0,decompressed_size);
13554  NK_ASSERT(decompressed_data);
13555  if (!decompressed_data) return 0;
13556  nk_decompress((unsigned char*)decompressed_data, (unsigned char*)compressed_data,
13557  (unsigned int)compressed_size);
13558 
13559  cfg = (config) ? *config: nk_font_config(height);
13560  cfg.ttf_blob = decompressed_data;
13561  cfg.ttf_size = decompressed_size;
13562  cfg.size = height;
13563  cfg.ttf_data_owned_by_atlas = 1;
13564  return nk_font_atlas_add(atlas, &cfg);
13565 }
13566 NK_API struct nk_font*
13567 nk_font_atlas_add_compressed_base85(struct nk_font_atlas *atlas,
13568  const char *data_base85, float height, const struct nk_font_config *config)
13569 {
13570  int compressed_size;
13571  void *compressed_data;
13572  struct nk_font *font;
13573 
13574  NK_ASSERT(atlas);
13575  NK_ASSERT(atlas->temporary.alloc);
13576  NK_ASSERT(atlas->temporary.free);
13577  NK_ASSERT(atlas->permanent.alloc);
13578  NK_ASSERT(atlas->permanent.free);
13579 
13580  NK_ASSERT(data_base85);
13581  if (!atlas || !data_base85 || !atlas->temporary.alloc || !atlas->temporary.free ||
13582  !atlas->permanent.alloc || !atlas->permanent.free)
13583  return 0;
13584 
13585  compressed_size = (((int)nk_strlen(data_base85) + 4) / 5) * 4;
13586  compressed_data = atlas->temporary.alloc(atlas->temporary.userdata,0, (nk_size)compressed_size);
13587  NK_ASSERT(compressed_data);
13588  if (!compressed_data) return 0;
13589  nk_decode_85((unsigned char*)compressed_data, (const unsigned char*)data_base85);
13590  font = nk_font_atlas_add_compressed(atlas, compressed_data,
13591  (nk_size)compressed_size, height, config);
13592  atlas->temporary.free(atlas->temporary.userdata, compressed_data);
13593  return font;
13594 }
13595 
13596 #ifdef NK_INCLUDE_DEFAULT_FONT
13597 NK_API struct nk_font*
13598 nk_font_atlas_add_default(struct nk_font_atlas *atlas,
13599  float pixel_height, const struct nk_font_config *config)
13600 {
13601  NK_ASSERT(atlas);
13602  NK_ASSERT(atlas->temporary.alloc);
13603  NK_ASSERT(atlas->temporary.free);
13604  NK_ASSERT(atlas->permanent.alloc);
13605  NK_ASSERT(atlas->permanent.free);
13606  return nk_font_atlas_add_compressed_base85(atlas,
13607  nk_proggy_clean_ttf_compressed_data_base85, pixel_height, config);
13608 }
13609 #endif
13610 NK_API const void*
13611 nk_font_atlas_bake(struct nk_font_atlas *atlas, int *width, int *height,
13612  enum nk_font_atlas_format fmt)
13613 {
13614  int i = 0;
13615  void *tmp = 0;
13616  nk_size tmp_size, img_size;
13617  struct nk_font *font_iter;
13618  struct nk_font_baker *baker;
13619 
13620  NK_ASSERT(atlas);
13621  NK_ASSERT(atlas->temporary.alloc);
13622  NK_ASSERT(atlas->temporary.free);
13623  NK_ASSERT(atlas->permanent.alloc);
13624  NK_ASSERT(atlas->permanent.free);
13625 
13626  NK_ASSERT(width);
13627  NK_ASSERT(height);
13628  if (!atlas || !width || !height ||
13629  !atlas->temporary.alloc || !atlas->temporary.free ||
13630  !atlas->permanent.alloc || !atlas->permanent.free)
13631  return 0;
13632 
13633 #ifdef NK_INCLUDE_DEFAULT_FONT
13634  /* no font added so just use default font */
13635  if (!atlas->font_num)
13636  atlas->default_font = nk_font_atlas_add_default(atlas, 13.0f, 0);
13637 #endif
13638  NK_ASSERT(atlas->font_num);
13639  if (!atlas->font_num) return 0;
13640 
13641  /* allocate temporary baker memory required for the baking process */
13642  nk_font_baker_memory(&tmp_size, &atlas->glyph_count, atlas->config, atlas->font_num);
13643  tmp = atlas->temporary.alloc(atlas->temporary.userdata,0, tmp_size);
13644  NK_ASSERT(tmp);
13645  if (!tmp) goto failed;
13646 
13647  /* allocate glyph memory for all fonts */
13648  baker = nk_font_baker(tmp, atlas->glyph_count, atlas->font_num, &atlas->temporary);
13649  atlas->glyphs = (struct nk_font_glyph*)atlas->permanent.alloc(
13650  atlas->permanent.userdata,0, sizeof(struct nk_font_glyph)*(nk_size)atlas->glyph_count);
13651  NK_ASSERT(atlas->glyphs);
13652  if (!atlas->glyphs)
13653  goto failed;
13654 
13655  /* pack all glyphs into a tight fit space */
13656  atlas->custom.w = (NK_CURSOR_DATA_W*2)+1;
13657  atlas->custom.h = NK_CURSOR_DATA_H + 1;
13658  if (!nk_font_bake_pack(baker, &img_size, width, height, &atlas->custom,
13659  atlas->config, atlas->font_num, &atlas->temporary))
13660  goto failed;
13661 
13662  /* allocate memory for the baked image font atlas */
13663  atlas->pixel = atlas->temporary.alloc(atlas->temporary.userdata,0, img_size);
13664  NK_ASSERT(atlas->pixel);
13665  if (!atlas->pixel)
13666  goto failed;
13667 
13668  /* bake glyphs and custom white pixel into image */
13669  nk_font_bake(baker, atlas->pixel, *width, *height,
13670  atlas->glyphs, atlas->glyph_count, atlas->config, atlas->font_num);
13671  nk_font_bake_custom_data(atlas->pixel, *width, *height, atlas->custom,
13672  nk_custom_cursor_data, NK_CURSOR_DATA_W, NK_CURSOR_DATA_H, '.', 'X');
13673 
13674  if (fmt == NK_FONT_ATLAS_RGBA32) {
13675  /* convert alpha8 image into rgba32 image */
13676  void *img_rgba = atlas->temporary.alloc(atlas->temporary.userdata,0,
13677  (nk_size)(*width * *height * 4));
13678  NK_ASSERT(img_rgba);
13679  if (!img_rgba) goto failed;
13680  nk_font_bake_convert(img_rgba, *width, *height, atlas->pixel);
13681  atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
13682  atlas->pixel = img_rgba;
13683  }
13684  atlas->tex_width = *width;
13685  atlas->tex_height = *height;
13686 
13687  /* initialize each font */
13688  for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) {
13689  struct nk_font *font = font_iter;
13690  struct nk_font_config *config = font->config;
13691  nk_font_init(font, config->size, config->fallback_glyph, atlas->glyphs,
13692  config->font, nk_handle_ptr(0));
13693  }
13694 
13695  /* initialize each cursor */
13696  {NK_STORAGE const struct nk_vec2 nk_cursor_data[NK_CURSOR_COUNT][3] = {
13697  /* Pos Size Offset */
13698  {{ 0, 3}, {12,19}, { 0, 0}},
13699  {{13, 0}, { 7,16}, { 4, 8}},
13700  {{31, 0}, {23,23}, {11,11}},
13701  {{21, 0}, { 9, 23}, { 5,11}},
13702  {{55,18}, {23, 9}, {11, 5}},
13703  {{73, 0}, {17,17}, { 9, 9}},
13704  {{55, 0}, {17,17}, { 9, 9}}
13705  };
13706  for (i = 0; i < NK_CURSOR_COUNT; ++i) {
13707  struct nk_cursor *cursor = &atlas->cursors[i];
13708  cursor->img.w = (unsigned short)*width;
13709  cursor->img.h = (unsigned short)*height;
13710  cursor->img.region[0] = (unsigned short)(atlas->custom.x + nk_cursor_data[i][0].x);
13711  cursor->img.region[1] = (unsigned short)(atlas->custom.y + nk_cursor_data[i][0].y);
13712  cursor->img.region[2] = (unsigned short)nk_cursor_data[i][1].x;
13713  cursor->img.region[3] = (unsigned short)nk_cursor_data[i][1].y;
13714  cursor->size = nk_cursor_data[i][1];
13715  cursor->offset = nk_cursor_data[i][2];
13716  }}
13717  /* free temporary memory */
13718  atlas->temporary.free(atlas->temporary.userdata, tmp);
13719  return atlas->pixel;
13720 
13721 failed:
13722  /* error so cleanup all memory */
13723  if (tmp) atlas->temporary.free(atlas->temporary.userdata, tmp);
13724  if (atlas->glyphs) {
13725  atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
13726  atlas->glyphs = 0;
13727  }
13728  if (atlas->pixel) {
13729  atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
13730  atlas->pixel = 0;
13731  }
13732  return 0;
13733 }
13734 NK_API void
13735 nk_font_atlas_end(struct nk_font_atlas *atlas, nk_handle texture,
13736  struct nk_draw_null_texture *null)
13737 {
13738  int i = 0;
13739  struct nk_font *font_iter;
13740  NK_ASSERT(atlas);
13741  if (!atlas) {
13742  if (!null) return;
13743  null->texture = texture;
13744  null->uv = nk_vec2(0.5f,0.5f);
13745  }
13746  if (null) {
13747  null->texture = texture;
13748  null->uv.x = (atlas->custom.x + 0.5f)/(float)atlas->tex_width;
13749  null->uv.y = (atlas->custom.y + 0.5f)/(float)atlas->tex_height;
13750  }
13751  for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) {
13752  font_iter->texture = texture;
13753 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
13754  font_iter->handle.texture = texture;
13755 #endif
13756  }
13757  for (i = 0; i < NK_CURSOR_COUNT; ++i)
13758  atlas->cursors[i].img.handle = texture;
13759 
13760  atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
13761  atlas->pixel = 0;
13762  atlas->tex_width = 0;
13763  atlas->tex_height = 0;
13764  atlas->custom.x = 0;
13765  atlas->custom.y = 0;
13766  atlas->custom.w = 0;
13767  atlas->custom.h = 0;
13768 }
13769 NK_API void
13770 nk_font_atlas_cleanup(struct nk_font_atlas *atlas)
13771 {
13772  NK_ASSERT(atlas);
13773  NK_ASSERT(atlas->temporary.alloc);
13774  NK_ASSERT(atlas->temporary.free);
13775  NK_ASSERT(atlas->permanent.alloc);
13776  NK_ASSERT(atlas->permanent.free);
13777  if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return;
13778  if (atlas->config) {
13779  struct nk_font_config *iter;
13780  for (iter = atlas->config; iter; iter = iter->next) {
13781  struct nk_font_config *i;
13782  for (i = iter->n; i != iter; i = i->n) {
13783  atlas->permanent.free(atlas->permanent.userdata, i->ttf_blob);
13784  i->ttf_blob = 0;
13785  }
13786  atlas->permanent.free(atlas->permanent.userdata, iter->ttf_blob);
13787  iter->ttf_blob = 0;
13788  }
13789  }
13790 }
13791 NK_API void
13792 nk_font_atlas_clear(struct nk_font_atlas *atlas)
13793 {
13794  NK_ASSERT(atlas);
13795  NK_ASSERT(atlas->temporary.alloc);
13796  NK_ASSERT(atlas->temporary.free);
13797  NK_ASSERT(atlas->permanent.alloc);
13798  NK_ASSERT(atlas->permanent.free);
13799  if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return;
13800 
13801  if (atlas->config) {
13802  struct nk_font_config *iter, *next;
13803  for (iter = atlas->config; iter; iter = next) {
13804  struct nk_font_config *i, *n;
13805  for (i = iter->n; i != iter; i = n) {
13806  n = i->n;
13807  if (i->ttf_blob)
13808  atlas->permanent.free(atlas->permanent.userdata, i->ttf_blob);
13809  atlas->permanent.free(atlas->permanent.userdata, i);
13810  }
13811  next = iter->next;
13812  if (i->ttf_blob)
13813  atlas->permanent.free(atlas->permanent.userdata, iter->ttf_blob);
13814  atlas->permanent.free(atlas->permanent.userdata, iter);
13815  }
13816  atlas->config = 0;
13817  }
13818  if (atlas->fonts) {
13819  struct nk_font *iter, *next;
13820  for (iter = atlas->fonts; iter; iter = next) {
13821  next = iter->next;
13822  atlas->permanent.free(atlas->permanent.userdata, iter);
13823  }
13824  atlas->fonts = 0;
13825  }
13826  if (atlas->glyphs)
13827  atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
13828  nk_zero_struct(*atlas);
13829 }
13830 #endif
13831 
13832 
13833 
13834 
13835 
13836 /* ===============================================================
13837  *
13838  * INPUT
13839  *
13840  * ===============================================================*/
13841 NK_API void
13842 nk_input_begin(struct nk_context *ctx)
13843 {
13844  int i;
13845  struct nk_input *in;
13846  NK_ASSERT(ctx);
13847  if (!ctx) return;
13848  in = &ctx->input;
13849  for (i = 0; i < NK_BUTTON_MAX; ++i)
13850  in->mouse.buttons[i].clicked = 0;
13851 
13852  in->keyboard.text_len = 0;
13853  in->mouse.scroll_delta = nk_vec2(0,0);
13854  in->mouse.prev.x = in->mouse.pos.x;
13855  in->mouse.prev.y = in->mouse.pos.y;
13856  in->mouse.delta.x = 0;
13857  in->mouse.delta.y = 0;
13858  for (i = 0; i < NK_KEY_MAX; i++)
13859  in->keyboard.keys[i].clicked = 0;
13860 }
13861 NK_API void
13862 nk_input_end(struct nk_context *ctx)
13863 {
13864  struct nk_input *in;
13865  NK_ASSERT(ctx);
13866  if (!ctx) return;
13867  in = &ctx->input;
13868  if (in->mouse.grab)
13869  in->mouse.grab = 0;
13870  if (in->mouse.ungrab) {
13871  in->mouse.grabbed = 0;
13872  in->mouse.ungrab = 0;
13873  in->mouse.grab = 0;
13874  }
13875 }
13876 NK_API void
13877 nk_input_motion(struct nk_context *ctx, int x, int y)
13878 {
13879  struct nk_input *in;
13880  NK_ASSERT(ctx);
13881  if (!ctx) return;
13882  in = &ctx->input;
13883  in->mouse.pos.x = (float)x;
13884  in->mouse.pos.y = (float)y;
13885  in->mouse.delta.x = in->mouse.pos.x - in->mouse.prev.x;
13886  in->mouse.delta.y = in->mouse.pos.y - in->mouse.prev.y;
13887 }
13888 NK_API void
13889 nk_input_key(struct nk_context *ctx, enum nk_keys key, int down)
13890 {
13891  struct nk_input *in;
13892  NK_ASSERT(ctx);
13893  if (!ctx) return;
13894  in = &ctx->input;
13895  if (in->keyboard.keys[key].down != down)
13896  in->keyboard.keys[key].clicked++;
13897  in->keyboard.keys[key].down = down;
13898 }
13899 NK_API void
13900 nk_input_button(struct nk_context *ctx, enum nk_buttons id, int x, int y, int down)
13901 {
13902  struct nk_mouse_button *btn;
13903  struct nk_input *in;
13904  NK_ASSERT(ctx);
13905  if (!ctx) return;
13906  in = &ctx->input;
13907  if (in->mouse.buttons[id].down == down) return;
13908 
13909  btn = &in->mouse.buttons[id];
13910  btn->clicked_pos.x = (float)x;
13911  btn->clicked_pos.y = (float)y;
13912  btn->down = down;
13913  btn->clicked++;
13914 }
13915 NK_API void
13916 nk_input_scroll(struct nk_context *ctx, struct nk_vec2 val)
13917 {
13918  NK_ASSERT(ctx);
13919  if (!ctx) return;
13920  ctx->input.mouse.scroll_delta.x += val.x;
13921  ctx->input.mouse.scroll_delta.y += val.y;
13922 }
13923 NK_API void
13924 nk_input_glyph(struct nk_context *ctx, const nk_glyph glyph)
13925 {
13926  int len = 0;
13927  nk_rune unicode;
13928  struct nk_input *in;
13929 
13930  NK_ASSERT(ctx);
13931  if (!ctx) return;
13932  in = &ctx->input;
13933 
13934  len = nk_utf_decode(glyph, &unicode, NK_UTF_SIZE);
13935  if (len && ((in->keyboard.text_len + len) < NK_INPUT_MAX)) {
13936  nk_utf_encode(unicode, &in->keyboard.text[in->keyboard.text_len],
13938  in->keyboard.text_len += len;
13939  }
13940 }
13941 NK_API void
13942 nk_input_char(struct nk_context *ctx, char c)
13943 {
13944  nk_glyph glyph;
13945  NK_ASSERT(ctx);
13946  if (!ctx) return;
13947  glyph[0] = c;
13948  nk_input_glyph(ctx, glyph);
13949 }
13950 NK_API void
13951 nk_input_unicode(struct nk_context *ctx, nk_rune unicode)
13952 {
13953  nk_glyph rune;
13954  NK_ASSERT(ctx);
13955  if (!ctx) return;
13956  nk_utf_encode(unicode, rune, NK_UTF_SIZE);
13957  nk_input_glyph(ctx, rune);
13958 }
13959 NK_API int
13960 nk_input_has_mouse_click(const struct nk_input *i, enum nk_buttons id)
13961 {
13962  const struct nk_mouse_button *btn;
13963  if (!i) return nk_false;
13964  btn = &i->mouse.buttons[id];
13965  return (btn->clicked && btn->down == nk_false) ? nk_true : nk_false;
13966 }
13967 NK_API int
13968 nk_input_has_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id,
13969  struct nk_rect b)
13970 {
13971  const struct nk_mouse_button *btn;
13972  if (!i) return nk_false;
13973  btn = &i->mouse.buttons[id];
13974  if (!NK_INBOX(btn->clicked_pos.x,btn->clicked_pos.y,b.x,b.y,b.w,b.h))
13975  return nk_false;
13976  return nk_true;
13977 }
13978 NK_API int
13980  struct nk_rect b, int down)
13981 {
13982  const struct nk_mouse_button *btn;
13983  if (!i) return nk_false;
13984  btn = &i->mouse.buttons[id];
13985  return nk_input_has_mouse_click_in_rect(i, id, b) && (btn->down == down);
13986 }
13987 NK_API int
13988 nk_input_is_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id,
13989  struct nk_rect b)
13990 {
13991  const struct nk_mouse_button *btn;
13992  if (!i) return nk_false;
13993  btn = &i->mouse.buttons[id];
13994  return (nk_input_has_mouse_click_down_in_rect(i, id, b, nk_false) &&
13995  btn->clicked) ? nk_true : nk_false;
13996 }
13997 NK_API int
13999  struct nk_rect b, int down)
14000 {
14001  const struct nk_mouse_button *btn;
14002  if (!i) return nk_false;
14003  btn = &i->mouse.buttons[id];
14004  return (nk_input_has_mouse_click_down_in_rect(i, id, b, down) &&
14005  btn->clicked) ? nk_true : nk_false;
14006 }
14007 NK_API int
14008 nk_input_any_mouse_click_in_rect(const struct nk_input *in, struct nk_rect b)
14009 {
14010  int i, down = 0;
14011  for (i = 0; i < NK_BUTTON_MAX; ++i)
14012  down = down || nk_input_is_mouse_click_in_rect(in, (enum nk_buttons)i, b);
14013  return down;
14014 }
14015 NK_API int
14016 nk_input_is_mouse_hovering_rect(const struct nk_input *i, struct nk_rect rect)
14017 {
14018  if (!i) return nk_false;
14019  return NK_INBOX(i->mouse.pos.x, i->mouse.pos.y, rect.x, rect.y, rect.w, rect.h);
14020 }
14021 NK_API int
14022 nk_input_is_mouse_prev_hovering_rect(const struct nk_input *i, struct nk_rect rect)
14023 {
14024  if (!i) return nk_false;
14025  return NK_INBOX(i->mouse.prev.x, i->mouse.prev.y, rect.x, rect.y, rect.w, rect.h);
14026 }
14027 NK_API int
14028 nk_input_mouse_clicked(const struct nk_input *i, enum nk_buttons id, struct nk_rect rect)
14029 {
14030  if (!i) return nk_false;
14031  if (!nk_input_is_mouse_hovering_rect(i, rect)) return nk_false;
14032  return nk_input_is_mouse_click_in_rect(i, id, rect);
14033 }
14034 NK_API int
14035 nk_input_is_mouse_down(const struct nk_input *i, enum nk_buttons id)
14036 {
14037  if (!i) return nk_false;
14038  return i->mouse.buttons[id].down;
14039 }
14040 NK_API int
14041 nk_input_is_mouse_pressed(const struct nk_input *i, enum nk_buttons id)
14042 {
14043  const struct nk_mouse_button *b;
14044  if (!i) return nk_false;
14045  b = &i->mouse.buttons[id];
14046  if (b->down && b->clicked)
14047  return nk_true;
14048  return nk_false;
14049 }
14050 NK_API int
14051 nk_input_is_mouse_released(const struct nk_input *i, enum nk_buttons id)
14052 {
14053  if (!i) return nk_false;
14054  return (!i->mouse.buttons[id].down && i->mouse.buttons[id].clicked);
14055 }
14056 NK_API int
14057 nk_input_is_key_pressed(const struct nk_input *i, enum nk_keys key)
14058 {
14059  const struct nk_key *k;
14060  if (!i) return nk_false;
14061  k = &i->keyboard.keys[key];
14062  if ((k->down && k->clicked) || (!k->down && k->clicked >= 2))
14063  return nk_true;
14064  return nk_false;
14065 }
14066 NK_API int
14067 nk_input_is_key_released(const struct nk_input *i, enum nk_keys key)
14068 {
14069  const struct nk_key *k;
14070  if (!i) return nk_false;
14071  k = &i->keyboard.keys[key];
14072  if ((!k->down && k->clicked) || (k->down && k->clicked >= 2))
14073  return nk_true;
14074  return nk_false;
14075 }
14076 NK_API int
14077 nk_input_is_key_down(const struct nk_input *i, enum nk_keys key)
14078 {
14079  const struct nk_key *k;
14080  if (!i) return nk_false;
14081  k = &i->keyboard.keys[key];
14082  if (k->down) return nk_true;
14083  return nk_false;
14084 }
14085 
14086 
14087 
14088 
14089 
14090 /* ===============================================================
14091  *
14092  * STYLE
14093  *
14094  * ===============================================================*/
14095 NK_API void nk_style_default(struct nk_context *ctx){nk_style_from_table(ctx, 0);}
14096 #define NK_COLOR_MAP(NK_COLOR)\
14097  NK_COLOR(NK_COLOR_TEXT, 175,175,175,255) \
14098  NK_COLOR(NK_COLOR_WINDOW, 45, 45, 45, 255) \
14099  NK_COLOR(NK_COLOR_HEADER, 40, 40, 40, 255) \
14100  NK_COLOR(NK_COLOR_BORDER, 65, 65, 65, 255) \
14101  NK_COLOR(NK_COLOR_BUTTON, 50, 50, 50, 255) \
14102  NK_COLOR(NK_COLOR_BUTTON_HOVER, 40, 40, 40, 255) \
14103  NK_COLOR(NK_COLOR_BUTTON_ACTIVE, 35, 35, 35, 255) \
14104  NK_COLOR(NK_COLOR_TOGGLE, 100,100,100,255) \
14105  NK_COLOR(NK_COLOR_TOGGLE_HOVER, 120,120,120,255) \
14106  NK_COLOR(NK_COLOR_TOGGLE_CURSOR, 45, 45, 45, 255) \
14107  NK_COLOR(NK_COLOR_SELECT, 45, 45, 45, 255) \
14108  NK_COLOR(NK_COLOR_SELECT_ACTIVE, 35, 35, 35,255) \
14109  NK_COLOR(NK_COLOR_SLIDER, 38, 38, 38, 255) \
14110  NK_COLOR(NK_COLOR_SLIDER_CURSOR, 100,100,100,255) \
14111  NK_COLOR(NK_COLOR_SLIDER_CURSOR_HOVER, 120,120,120,255) \
14112  NK_COLOR(NK_COLOR_SLIDER_CURSOR_ACTIVE, 150,150,150,255) \
14113  NK_COLOR(NK_COLOR_PROPERTY, 38, 38, 38, 255) \
14114  NK_COLOR(NK_COLOR_EDIT, 38, 38, 38, 255) \
14115  NK_COLOR(NK_COLOR_EDIT_CURSOR, 175,175,175,255) \
14116  NK_COLOR(NK_COLOR_COMBO, 45, 45, 45, 255) \
14117  NK_COLOR(NK_COLOR_CHART, 120,120,120,255) \
14118  NK_COLOR(NK_COLOR_CHART_COLOR, 45, 45, 45, 255) \
14119  NK_COLOR(NK_COLOR_CHART_COLOR_HIGHLIGHT, 255, 0, 0, 255) \
14120  NK_COLOR(NK_COLOR_SCROLLBAR, 40, 40, 40, 255) \
14121  NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR, 100,100,100,255) \
14122  NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_HOVER, 120,120,120,255) \
14123  NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_ACTIVE, 150,150,150,255) \
14124  NK_COLOR(NK_COLOR_TAB_HEADER, 40, 40, 40,255)
14125 
14126 NK_GLOBAL const struct nk_color
14127 nk_default_color_style[NK_COLOR_COUNT] = {
14128 #define NK_COLOR(a,b,c,d,e) {b,c,d,e},
14129  NK_COLOR_MAP(NK_COLOR)
14130 #undef NK_COLOR
14131 };
14132 NK_GLOBAL const char *nk_color_names[NK_COLOR_COUNT] = {
14133 #define NK_COLOR(a,b,c,d,e) #a,
14134  NK_COLOR_MAP(NK_COLOR)
14135 #undef NK_COLOR
14136 };
14137 
14138 NK_API const char*
14140 {
14141  return nk_color_names[c];
14142 }
14143 NK_API struct nk_style_item
14144 nk_style_item_image(struct nk_image img)
14145 {
14146  struct nk_style_item i;
14147  i.type = NK_STYLE_ITEM_IMAGE;
14148  i.data.image = img;
14149  return i;
14150 }
14151 NK_API struct nk_style_item
14152 nk_style_item_color(struct nk_color col)
14153 {
14154  struct nk_style_item i;
14155  i.type = NK_STYLE_ITEM_COLOR;
14156  i.data.color = col;
14157  return i;
14158 }
14159 NK_API struct nk_style_item
14160 nk_style_item_hide(void)
14161 {
14162  struct nk_style_item i;
14163  i.type = NK_STYLE_ITEM_COLOR;
14164  i.data.color = nk_rgba(0,0,0,0);
14165  return i;
14166 }
14167 NK_API void
14168 nk_style_from_table(struct nk_context *ctx, const struct nk_color *table)
14169 {
14170  struct nk_style *style;
14171  struct nk_style_text *text;
14172  struct nk_style_button *button;
14173  struct nk_style_toggle *toggle;
14174  struct nk_style_selectable *select;
14175  struct nk_style_slider *slider;
14176  struct nk_style_progress *prog;
14177  struct nk_style_scrollbar *scroll;
14178  struct nk_style_edit *edit;
14179  struct nk_style_property *property;
14180  struct nk_style_combo *combo;
14181  struct nk_style_chart *chart;
14182  struct nk_style_tab *tab;
14183  struct nk_style_window *win;
14184 
14185  NK_ASSERT(ctx);
14186  if (!ctx) return;
14187  style = &ctx->style;
14188  table = (!table) ? nk_default_color_style: table;
14189 
14190  /* default text */
14191  text = &style->text;
14192  text->color = table[NK_COLOR_TEXT];
14193  text->padding = nk_vec2(0,0);
14194 
14195  /* default button */
14196  button = &style->button;
14197  nk_zero_struct(*button);
14198  button->normal = nk_style_item_color(table[NK_COLOR_BUTTON]);
14201  button->border_color = table[NK_COLOR_BORDER];
14202  button->text_background = table[NK_COLOR_BUTTON];
14203  button->text_normal = table[NK_COLOR_TEXT];
14204  button->text_hover = table[NK_COLOR_TEXT];
14205  button->text_active = table[NK_COLOR_TEXT];
14206  button->padding = nk_vec2(2.0f,2.0f);
14207  button->image_padding = nk_vec2(0.0f,0.0f);
14208  button->touch_padding = nk_vec2(0.0f, 0.0f);
14209  button->userdata = nk_handle_ptr(0);
14210  button->text_alignment = NK_TEXT_CENTERED;
14211  button->border = 1.0f;
14212  button->rounding = 4.0f;
14213  button->draw_begin = 0;
14214  button->draw_end = 0;
14215 
14216  /* contextual button */
14217  button = &style->contextual_button;
14218  nk_zero_struct(*button);
14219  button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]);
14222  button->border_color = table[NK_COLOR_WINDOW];
14223  button->text_background = table[NK_COLOR_WINDOW];
14224  button->text_normal = table[NK_COLOR_TEXT];
14225  button->text_hover = table[NK_COLOR_TEXT];
14226  button->text_active = table[NK_COLOR_TEXT];
14227  button->padding = nk_vec2(2.0f,2.0f);
14228  button->touch_padding = nk_vec2(0.0f,0.0f);
14229  button->userdata = nk_handle_ptr(0);
14230  button->text_alignment = NK_TEXT_CENTERED;
14231  button->border = 0.0f;
14232  button->rounding = 0.0f;
14233  button->draw_begin = 0;
14234  button->draw_end = 0;
14235 
14236  /* menu button */
14237  button = &style->menu_button;
14238  nk_zero_struct(*button);
14239  button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]);
14240  button->hover = nk_style_item_color(table[NK_COLOR_WINDOW]);
14241  button->active = nk_style_item_color(table[NK_COLOR_WINDOW]);
14242  button->border_color = table[NK_COLOR_WINDOW];
14243  button->text_background = table[NK_COLOR_WINDOW];
14244  button->text_normal = table[NK_COLOR_TEXT];
14245  button->text_hover = table[NK_COLOR_TEXT];
14246  button->text_active = table[NK_COLOR_TEXT];
14247  button->padding = nk_vec2(2.0f,2.0f);
14248  button->touch_padding = nk_vec2(0.0f,0.0f);
14249  button->userdata = nk_handle_ptr(0);
14250  button->text_alignment = NK_TEXT_CENTERED;
14251  button->border = 0.0f;
14252  button->rounding = 1.0f;
14253  button->draw_begin = 0;
14254  button->draw_end = 0;
14255 
14256  /* checkbox toggle */
14257  toggle = &style->checkbox;
14258  nk_zero_struct(*toggle);
14259  toggle->normal = nk_style_item_color(table[NK_COLOR_TOGGLE]);
14264  toggle->userdata = nk_handle_ptr(0);
14265  toggle->text_background = table[NK_COLOR_WINDOW];
14266  toggle->text_normal = table[NK_COLOR_TEXT];
14267  toggle->text_hover = table[NK_COLOR_TEXT];
14268  toggle->text_active = table[NK_COLOR_TEXT];
14269  toggle->padding = nk_vec2(2.0f, 2.0f);
14270  toggle->touch_padding = nk_vec2(0,0);
14271  toggle->border_color = nk_rgba(0,0,0,0);
14272  toggle->border = 0.0f;
14273  toggle->spacing = 4;
14274 
14275  /* option toggle */
14276  toggle = &style->option;
14277  nk_zero_struct(*toggle);
14278  toggle->normal = nk_style_item_color(table[NK_COLOR_TOGGLE]);
14283  toggle->userdata = nk_handle_ptr(0);
14284  toggle->text_background = table[NK_COLOR_WINDOW];
14285  toggle->text_normal = table[NK_COLOR_TEXT];
14286  toggle->text_hover = table[NK_COLOR_TEXT];
14287  toggle->text_active = table[NK_COLOR_TEXT];
14288  toggle->padding = nk_vec2(3.0f, 3.0f);
14289  toggle->touch_padding = nk_vec2(0,0);
14290  toggle->border_color = nk_rgba(0,0,0,0);
14291  toggle->border = 0.0f;
14292  toggle->spacing = 4;
14293 
14294  /* selectable */
14295  select = &style->selectable;
14296  nk_zero_struct(*select);
14297  select->normal = nk_style_item_color(table[NK_COLOR_SELECT]);
14298  select->hover = nk_style_item_color(table[NK_COLOR_SELECT]);
14299  select->pressed = nk_style_item_color(table[NK_COLOR_SELECT]);
14303  select->text_normal = table[NK_COLOR_TEXT];
14304  select->text_hover = table[NK_COLOR_TEXT];
14305  select->text_pressed = table[NK_COLOR_TEXT];
14306  select->text_normal_active = table[NK_COLOR_TEXT];
14307  select->text_hover_active = table[NK_COLOR_TEXT];
14308  select->text_pressed_active = table[NK_COLOR_TEXT];
14309  select->padding = nk_vec2(2.0f,2.0f);
14310  select->image_padding = nk_vec2(2.0f,2.0f);
14311  select->touch_padding = nk_vec2(0,0);
14312  select->userdata = nk_handle_ptr(0);
14313  select->rounding = 0.0f;
14314  select->draw_begin = 0;
14315  select->draw_end = 0;
14316 
14317  /* slider */
14318  slider = &style->slider;
14319  nk_zero_struct(*slider);
14320  slider->normal = nk_style_item_hide();
14321  slider->hover = nk_style_item_hide();
14322  slider->active = nk_style_item_hide();
14323  slider->bar_normal = table[NK_COLOR_SLIDER];
14324  slider->bar_hover = table[NK_COLOR_SLIDER];
14325  slider->bar_active = table[NK_COLOR_SLIDER];
14326  slider->bar_filled = table[NK_COLOR_SLIDER_CURSOR];
14332  slider->cursor_size = nk_vec2(16,16);
14333  slider->padding = nk_vec2(2,2);
14334  slider->spacing = nk_vec2(2,2);
14335  slider->userdata = nk_handle_ptr(0);
14336  slider->show_buttons = nk_false;
14337  slider->bar_height = 8;
14338  slider->rounding = 0;
14339  slider->draw_begin = 0;
14340  slider->draw_end = 0;
14341 
14342  /* slider buttons */
14343  button = &style->slider.inc_button;
14344  button->normal = nk_style_item_color(nk_rgb(40,40,40));
14345  button->hover = nk_style_item_color(nk_rgb(42,42,42));
14346  button->active = nk_style_item_color(nk_rgb(44,44,44));
14347  button->border_color = nk_rgb(65,65,65);
14348  button->text_background = nk_rgb(40,40,40);
14349  button->text_normal = nk_rgb(175,175,175);
14350  button->text_hover = nk_rgb(175,175,175);
14351  button->text_active = nk_rgb(175,175,175);
14352  button->padding = nk_vec2(8.0f,8.0f);
14353  button->touch_padding = nk_vec2(0.0f,0.0f);
14354  button->userdata = nk_handle_ptr(0);
14355  button->text_alignment = NK_TEXT_CENTERED;
14356  button->border = 1.0f;
14357  button->rounding = 0.0f;
14358  button->draw_begin = 0;
14359  button->draw_end = 0;
14360  style->slider.dec_button = style->slider.inc_button;
14361 
14362  /* progressbar */
14363  prog = &style->progress;
14364  nk_zero_struct(*prog);
14365  prog->normal = nk_style_item_color(table[NK_COLOR_SLIDER]);
14366  prog->hover = nk_style_item_color(table[NK_COLOR_SLIDER]);
14367  prog->active = nk_style_item_color(table[NK_COLOR_SLIDER]);
14371  prog->border_color = nk_rgba(0,0,0,0);
14372  prog->cursor_border_color = nk_rgba(0,0,0,0);
14373  prog->userdata = nk_handle_ptr(0);
14374  prog->padding = nk_vec2(4,4);
14375  prog->rounding = 0;
14376  prog->border = 0;
14377  prog->cursor_rounding = 0;
14378  prog->cursor_border = 0;
14379  prog->draw_begin = 0;
14380  prog->draw_end = 0;
14381 
14382  /* scrollbars */
14383  scroll = &style->scrollh;
14384  nk_zero_struct(*scroll);
14385  scroll->normal = nk_style_item_color(table[NK_COLOR_SCROLLBAR]);
14386  scroll->hover = nk_style_item_color(table[NK_COLOR_SCROLLBAR]);
14387  scroll->active = nk_style_item_color(table[NK_COLOR_SCROLLBAR]);
14393  scroll->userdata = nk_handle_ptr(0);
14394  scroll->border_color = table[NK_COLOR_SCROLLBAR];
14395  scroll->cursor_border_color = table[NK_COLOR_SCROLLBAR];
14396  scroll->padding = nk_vec2(0,0);
14397  scroll->show_buttons = nk_false;
14398  scroll->border = 0;
14399  scroll->rounding = 0;
14400  scroll->border_cursor = 0;
14401  scroll->rounding_cursor = 0;
14402  scroll->draw_begin = 0;
14403  scroll->draw_end = 0;
14404  style->scrollv = style->scrollh;
14405 
14406  /* scrollbars buttons */
14407  button = &style->scrollh.inc_button;
14408  button->normal = nk_style_item_color(nk_rgb(40,40,40));
14409  button->hover = nk_style_item_color(nk_rgb(42,42,42));
14410  button->active = nk_style_item_color(nk_rgb(44,44,44));
14411  button->border_color = nk_rgb(65,65,65);
14412  button->text_background = nk_rgb(40,40,40);
14413  button->text_normal = nk_rgb(175,175,175);
14414  button->text_hover = nk_rgb(175,175,175);
14415  button->text_active = nk_rgb(175,175,175);
14416  button->padding = nk_vec2(4.0f,4.0f);
14417  button->touch_padding = nk_vec2(0.0f,0.0f);
14418  button->userdata = nk_handle_ptr(0);
14419  button->text_alignment = NK_TEXT_CENTERED;
14420  button->border = 1.0f;
14421  button->rounding = 0.0f;
14422  button->draw_begin = 0;
14423  button->draw_end = 0;
14424  style->scrollh.dec_button = style->scrollh.inc_button;
14425  style->scrollv.inc_button = style->scrollh.inc_button;
14426  style->scrollv.dec_button = style->scrollh.inc_button;
14427 
14428  /* edit */
14429  edit = &style->edit;
14430  nk_zero_struct(*edit);
14431  edit->normal = nk_style_item_color(table[NK_COLOR_EDIT]);
14432  edit->hover = nk_style_item_color(table[NK_COLOR_EDIT]);
14433  edit->active = nk_style_item_color(table[NK_COLOR_EDIT]);
14434  edit->cursor_normal = table[NK_COLOR_TEXT];
14435  edit->cursor_hover = table[NK_COLOR_TEXT];
14436  edit->cursor_text_normal= table[NK_COLOR_EDIT];
14437  edit->cursor_text_hover = table[NK_COLOR_EDIT];
14438  edit->border_color = table[NK_COLOR_BORDER];
14439  edit->text_normal = table[NK_COLOR_TEXT];
14440  edit->text_hover = table[NK_COLOR_TEXT];
14441  edit->text_active = table[NK_COLOR_TEXT];
14442  edit->selected_normal = table[NK_COLOR_TEXT];
14443  edit->selected_hover = table[NK_COLOR_TEXT];
14444  edit->selected_text_normal = table[NK_COLOR_EDIT];
14445  edit->selected_text_hover = table[NK_COLOR_EDIT];
14446  edit->scrollbar_size = nk_vec2(10,10);
14447  edit->scrollbar = style->scrollv;
14448  edit->padding = nk_vec2(4,4);
14449  edit->row_padding = 2;
14450  edit->cursor_size = 4;
14451  edit->border = 1;
14452  edit->rounding = 0;
14453 
14454  /* property */
14455  property = &style->property;
14456  nk_zero_struct(*property);
14457  property->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]);
14458  property->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]);
14459  property->active = nk_style_item_color(table[NK_COLOR_PROPERTY]);
14460  property->border_color = table[NK_COLOR_BORDER];
14461  property->label_normal = table[NK_COLOR_TEXT];
14462  property->label_hover = table[NK_COLOR_TEXT];
14463  property->label_active = table[NK_COLOR_TEXT];
14464  property->sym_left = NK_SYMBOL_TRIANGLE_LEFT;
14465  property->sym_right = NK_SYMBOL_TRIANGLE_RIGHT;
14466  property->userdata = nk_handle_ptr(0);
14467  property->padding = nk_vec2(4,4);
14468  property->border = 1;
14469  property->rounding = 10;
14470  property->draw_begin = 0;
14471  property->draw_end = 0;
14472 
14473  /* property buttons */
14474  button = &style->property.dec_button;
14475  nk_zero_struct(*button);
14476  button->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]);
14477  button->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]);
14478  button->active = nk_style_item_color(table[NK_COLOR_PROPERTY]);
14479  button->border_color = nk_rgba(0,0,0,0);
14480  button->text_background = table[NK_COLOR_PROPERTY];
14481  button->text_normal = table[NK_COLOR_TEXT];
14482  button->text_hover = table[NK_COLOR_TEXT];
14483  button->text_active = table[NK_COLOR_TEXT];
14484  button->padding = nk_vec2(0.0f,0.0f);
14485  button->touch_padding = nk_vec2(0.0f,0.0f);
14486  button->userdata = nk_handle_ptr(0);
14487  button->text_alignment = NK_TEXT_CENTERED;
14488  button->border = 0.0f;
14489  button->rounding = 0.0f;
14490  button->draw_begin = 0;
14491  button->draw_end = 0;
14492  style->property.inc_button = style->property.dec_button;
14493 
14494  /* property edit */
14495  edit = &style->property.edit;
14496  nk_zero_struct(*edit);
14500  edit->border_color = nk_rgba(0,0,0,0);
14501  edit->cursor_normal = table[NK_COLOR_TEXT];
14502  edit->cursor_hover = table[NK_COLOR_TEXT];
14503  edit->cursor_text_normal= table[NK_COLOR_EDIT];
14504  edit->cursor_text_hover = table[NK_COLOR_EDIT];
14505  edit->text_normal = table[NK_COLOR_TEXT];
14506  edit->text_hover = table[NK_COLOR_TEXT];
14507  edit->text_active = table[NK_COLOR_TEXT];
14508  edit->selected_normal = table[NK_COLOR_TEXT];
14509  edit->selected_hover = table[NK_COLOR_TEXT];
14510  edit->selected_text_normal = table[NK_COLOR_EDIT];
14511  edit->selected_text_hover = table[NK_COLOR_EDIT];
14512  edit->padding = nk_vec2(0,0);
14513  edit->cursor_size = 8;
14514  edit->border = 0;
14515  edit->rounding = 0;
14516 
14517  /* chart */
14518  chart = &style->chart;
14519  nk_zero_struct(*chart);
14521  chart->border_color = table[NK_COLOR_BORDER];
14523  chart->color = table[NK_COLOR_CHART_COLOR];
14524  chart->padding = nk_vec2(4,4);
14525  chart->border = 0;
14526  chart->rounding = 0;
14527 
14528  /* combo */
14529  combo = &style->combo;
14530  combo->normal = nk_style_item_color(table[NK_COLOR_COMBO]);
14531  combo->hover = nk_style_item_color(table[NK_COLOR_COMBO]);
14532  combo->active = nk_style_item_color(table[NK_COLOR_COMBO]);
14533  combo->border_color = table[NK_COLOR_BORDER];
14534  combo->label_normal = table[NK_COLOR_TEXT];
14535  combo->label_hover = table[NK_COLOR_TEXT];
14536  combo->label_active = table[NK_COLOR_TEXT];
14540  combo->content_padding = nk_vec2(4,4);
14541  combo->button_padding = nk_vec2(0,4);
14542  combo->spacing = nk_vec2(4,0);
14543  combo->border = 1;
14544  combo->rounding = 0;
14545 
14546  /* combo button */
14547  button = &style->combo.button;
14548  nk_zero_struct(*button);
14549  button->normal = nk_style_item_color(table[NK_COLOR_COMBO]);
14550  button->hover = nk_style_item_color(table[NK_COLOR_COMBO]);
14551  button->active = nk_style_item_color(table[NK_COLOR_COMBO]);
14552  button->border_color = nk_rgba(0,0,0,0);
14553  button->text_background = table[NK_COLOR_COMBO];
14554  button->text_normal = table[NK_COLOR_TEXT];
14555  button->text_hover = table[NK_COLOR_TEXT];
14556  button->text_active = table[NK_COLOR_TEXT];
14557  button->padding = nk_vec2(2.0f,2.0f);
14558  button->touch_padding = nk_vec2(0.0f,0.0f);
14559  button->userdata = nk_handle_ptr(0);
14560  button->text_alignment = NK_TEXT_CENTERED;
14561  button->border = 0.0f;
14562  button->rounding = 0.0f;
14563  button->draw_begin = 0;
14564  button->draw_end = 0;
14565 
14566  /* tab */
14567  tab = &style->tab;
14569  tab->border_color = table[NK_COLOR_BORDER];
14570  tab->text = table[NK_COLOR_TEXT];
14573  tab->padding = nk_vec2(4,4);
14574  tab->spacing = nk_vec2(4,4);
14575  tab->indent = 10.0f;
14576  tab->border = 1;
14577  tab->rounding = 0;
14578 
14579  /* tab button */
14580  button = &style->tab.tab_minimize_button;
14581  nk_zero_struct(*button);
14583  button->hover = nk_style_item_color(table[NK_COLOR_TAB_HEADER]);
14585  button->border_color = nk_rgba(0,0,0,0);
14586  button->text_background = table[NK_COLOR_TAB_HEADER];
14587  button->text_normal = table[NK_COLOR_TEXT];
14588  button->text_hover = table[NK_COLOR_TEXT];
14589  button->text_active = table[NK_COLOR_TEXT];
14590  button->padding = nk_vec2(2.0f,2.0f);
14591  button->touch_padding = nk_vec2(0.0f,0.0f);
14592  button->userdata = nk_handle_ptr(0);
14593  button->text_alignment = NK_TEXT_CENTERED;
14594  button->border = 0.0f;
14595  button->rounding = 0.0f;
14596  button->draw_begin = 0;
14597  button->draw_end = 0;
14598  style->tab.tab_maximize_button =*button;
14599 
14600  /* node button */
14601  button = &style->tab.node_minimize_button;
14602  nk_zero_struct(*button);
14603  button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]);
14604  button->hover = nk_style_item_color(table[NK_COLOR_WINDOW]);
14605  button->active = nk_style_item_color(table[NK_COLOR_WINDOW]);
14606  button->border_color = nk_rgba(0,0,0,0);
14607  button->text_background = table[NK_COLOR_TAB_HEADER];
14608  button->text_normal = table[NK_COLOR_TEXT];
14609  button->text_hover = table[NK_COLOR_TEXT];
14610  button->text_active = table[NK_COLOR_TEXT];
14611  button->padding = nk_vec2(2.0f,2.0f);
14612  button->touch_padding = nk_vec2(0.0f,0.0f);
14613  button->userdata = nk_handle_ptr(0);
14614  button->text_alignment = NK_TEXT_CENTERED;
14615  button->border = 0.0f;
14616  button->rounding = 0.0f;
14617  button->draw_begin = 0;
14618  button->draw_end = 0;
14619  style->tab.node_maximize_button =*button;
14620 
14621  /* window header */
14622  win = &style->window;
14623  win->header.align = NK_HEADER_RIGHT;
14630  win->header.label_normal = table[NK_COLOR_TEXT];
14631  win->header.label_hover = table[NK_COLOR_TEXT];
14632  win->header.label_active = table[NK_COLOR_TEXT];
14633  win->header.label_padding = nk_vec2(4,4);
14634  win->header.padding = nk_vec2(4,4);
14635  win->header.spacing = nk_vec2(0,0);
14636 
14637  /* window header close button */
14638  button = &style->window.header.close_button;
14639  nk_zero_struct(*button);
14640  button->normal = nk_style_item_color(table[NK_COLOR_HEADER]);
14641  button->hover = nk_style_item_color(table[NK_COLOR_HEADER]);
14642  button->active = nk_style_item_color(table[NK_COLOR_HEADER]);
14643  button->border_color = nk_rgba(0,0,0,0);
14644  button->text_background = table[NK_COLOR_HEADER];
14645  button->text_normal = table[NK_COLOR_TEXT];
14646  button->text_hover = table[NK_COLOR_TEXT];
14647  button->text_active = table[NK_COLOR_TEXT];
14648  button->padding = nk_vec2(0.0f,0.0f);
14649  button->touch_padding = nk_vec2(0.0f,0.0f);
14650  button->userdata = nk_handle_ptr(0);
14651  button->text_alignment = NK_TEXT_CENTERED;
14652  button->border = 0.0f;
14653  button->rounding = 0.0f;
14654  button->draw_begin = 0;
14655  button->draw_end = 0;
14656 
14657  /* window header minimize button */
14658  button = &style->window.header.minimize_button;
14659  nk_zero_struct(*button);
14660  button->normal = nk_style_item_color(table[NK_COLOR_HEADER]);
14661  button->hover = nk_style_item_color(table[NK_COLOR_HEADER]);
14662  button->active = nk_style_item_color(table[NK_COLOR_HEADER]);
14663  button->border_color = nk_rgba(0,0,0,0);
14664  button->text_background = table[NK_COLOR_HEADER];
14665  button->text_normal = table[NK_COLOR_TEXT];
14666  button->text_hover = table[NK_COLOR_TEXT];
14667  button->text_active = table[NK_COLOR_TEXT];
14668  button->padding = nk_vec2(0.0f,0.0f);
14669  button->touch_padding = nk_vec2(0.0f,0.0f);
14670  button->userdata = nk_handle_ptr(0);
14671  button->text_alignment = NK_TEXT_CENTERED;
14672  button->border = 0.0f;
14673  button->rounding = 0.0f;
14674  button->draw_begin = 0;
14675  button->draw_end = 0;
14676 
14677  /* window */
14678  win->background = table[NK_COLOR_WINDOW];
14680  win->border_color = table[NK_COLOR_BORDER];
14681  win->popup_border_color = table[NK_COLOR_BORDER];
14682  win->combo_border_color = table[NK_COLOR_BORDER];
14684  win->menu_border_color = table[NK_COLOR_BORDER];
14685  win->group_border_color = table[NK_COLOR_BORDER];
14686  win->tooltip_border_color = table[NK_COLOR_BORDER];
14687  win->scaler = nk_style_item_color(table[NK_COLOR_TEXT]);
14688 
14689  win->rounding = 0.0f;
14690  win->spacing = nk_vec2(4,4);
14691  win->scrollbar_size = nk_vec2(10,10);
14692  win->min_size = nk_vec2(64,64);
14693 
14694  win->combo_border = 1.0f;
14695  win->contextual_border = 1.0f;
14696  win->menu_border = 1.0f;
14697  win->group_border = 1.0f;
14698  win->tooltip_border = 1.0f;
14699  win->popup_border = 1.0f;
14700  win->border = 2.0f;
14701  win->min_row_height_padding = 8;
14702 
14703  win->padding = nk_vec2(4,4);
14704  win->group_padding = nk_vec2(4,4);
14705  win->popup_padding = nk_vec2(4,4);
14706  win->combo_padding = nk_vec2(4,4);
14707  win->contextual_padding = nk_vec2(4,4);
14708  win->menu_padding = nk_vec2(4,4);
14709  win->tooltip_padding = nk_vec2(4,4);
14710 }
14711 NK_API void
14712 nk_style_set_font(struct nk_context *ctx, const struct nk_user_font *font)
14713 {
14714  struct nk_style *style;
14715  NK_ASSERT(ctx);
14716 
14717  if (!ctx) return;
14718  style = &ctx->style;
14719  style->font = font;
14720  ctx->stacks.fonts.head = 0;
14721  if (ctx->current)
14723 }
14724 NK_API int
14725 nk_style_push_font(struct nk_context *ctx, const struct nk_user_font *font)
14726 {
14727  struct nk_config_stack_user_font *font_stack;
14728  struct nk_config_stack_user_font_element *element;
14729 
14730  NK_ASSERT(ctx);
14731  if (!ctx) return 0;
14732 
14733  font_stack = &ctx->stacks.fonts;
14734  NK_ASSERT(font_stack->head < (int)NK_LEN(font_stack->elements));
14735  if (font_stack->head >= (int)NK_LEN(font_stack->elements))
14736  return 0;
14737 
14738  element = &font_stack->elements[font_stack->head++];
14739  element->address = &ctx->style.font;
14740  element->old_value = ctx->style.font;
14741  ctx->style.font = font;
14742  return 1;
14743 }
14744 NK_API int
14745 nk_style_pop_font(struct nk_context *ctx)
14746 {
14747  struct nk_config_stack_user_font *font_stack;
14748  struct nk_config_stack_user_font_element *element;
14749 
14750  NK_ASSERT(ctx);
14751  if (!ctx) return 0;
14752 
14753  font_stack = &ctx->stacks.fonts;
14754  NK_ASSERT(font_stack->head > 0);
14755  if (font_stack->head < 1)
14756  return 0;
14757 
14758  element = &font_stack->elements[--font_stack->head];
14759  *element->address = element->old_value;
14760  return 1;
14761 }
14762 #define NK_STYLE_PUSH_IMPLEMENATION(prefix, type, stack) \
14763 nk_style_push_##type(struct nk_context *ctx, prefix##_##type *address, prefix##_##type value)\
14764 {\
14765  struct nk_config_stack_##type * type_stack;\
14766  struct nk_config_stack_##type##_element *element;\
14767  NK_ASSERT(ctx);\
14768  if (!ctx) return 0;\
14769  type_stack = &ctx->stacks.stack;\
14770  NK_ASSERT(type_stack->head < (int)NK_LEN(type_stack->elements));\
14771  if (type_stack->head >= (int)NK_LEN(type_stack->elements))\
14772  return 0;\
14773  element = &type_stack->elements[type_stack->head++];\
14774  element->address = address;\
14775  element->old_value = *address;\
14776  *address = value;\
14777  return 1;\
14778 }
14779 #define NK_STYLE_POP_IMPLEMENATION(type, stack) \
14780 nk_style_pop_##type(struct nk_context *ctx)\
14781 {\
14782  struct nk_config_stack_##type *type_stack;\
14783  struct nk_config_stack_##type##_element *element;\
14784  NK_ASSERT(ctx);\
14785  if (!ctx) return 0;\
14786  type_stack = &ctx->stacks.stack;\
14787  NK_ASSERT(type_stack->head > 0);\
14788  if (type_stack->head < 1)\
14789  return 0;\
14790  element = &type_stack->elements[--type_stack->head];\
14791  *element->address = element->old_value;\
14792  return 1;\
14793 }
14794 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk, style_item, style_items)
14795 NK_API int NK_STYLE_PUSH_IMPLEMENATION(nk,float, floats)
14796 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk, vec2, vectors)
14797 NK_API int NK_STYLE_PUSH_IMPLEMENATION(nk,flags, flags)
14798 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk,color, colors)
14799 
14800 NK_API int NK_STYLE_POP_IMPLEMENATION(style_item, style_items)
14801 NK_API int NK_STYLE_POP_IMPLEMENATION(float,floats)
14802 NK_API int NK_STYLE_POP_IMPLEMENATION(vec2, vectors)
14803 NK_API int NK_STYLE_POP_IMPLEMENATION(flags,flags)
14804 NK_API int NK_STYLE_POP_IMPLEMENATION(color,colors)
14805 
14806 NK_API int
14807 nk_style_set_cursor(struct nk_context *ctx, enum nk_style_cursor c)
14808 {
14809  struct nk_style *style;
14810  NK_ASSERT(ctx);
14811  if (!ctx) return 0;
14812  style = &ctx->style;
14813  if (style->cursors[c]) {
14814  style->cursor_active = style->cursors[c];
14815  return 1;
14816  }
14817  return 0;
14818 }
14819 NK_API void
14820 nk_style_show_cursor(struct nk_context *ctx)
14821 {
14822  ctx->style.cursor_visible = nk_true;
14823 }
14824 NK_API void
14825 nk_style_hide_cursor(struct nk_context *ctx)
14826 {
14827  ctx->style.cursor_visible = nk_false;
14828 }
14829 NK_API void
14830 nk_style_load_cursor(struct nk_context *ctx, enum nk_style_cursor cursor,
14831  const struct nk_cursor *c)
14832 {
14833  struct nk_style *style;
14834  NK_ASSERT(ctx);
14835  if (!ctx) return;
14836  style = &ctx->style;
14837  style->cursors[cursor] = c;
14838 }
14839 NK_API void
14841 {
14842  int i = 0;
14843  struct nk_style *style;
14844  NK_ASSERT(ctx);
14845  if (!ctx) return;
14846  style = &ctx->style;
14847  for (i = 0; i < NK_CURSOR_COUNT; ++i)
14848  style->cursors[i] = &cursors[i];
14849  style->cursor_visible = nk_true;
14850 }
14851 
14852 
14853 
14854 
14855 
14856 /* ==============================================================
14857  *
14858  * CONTEXT
14859  *
14860  * ===============================================================*/
14861 NK_INTERN void
14862 nk_setup(struct nk_context *ctx, const struct nk_user_font *font)
14863 {
14864  NK_ASSERT(ctx);
14865  if (!ctx) return;
14866  nk_zero_struct(*ctx);
14867  nk_style_default(ctx);
14868  ctx->seq = 1;
14869  if (font) ctx->style.font = font;
14870 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
14871  nk_draw_list_init(&ctx->draw_list);
14872 #endif
14873 }
14874 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
14875 NK_API int
14876 nk_init_default(struct nk_context *ctx, const struct nk_user_font *font)
14877 {
14878  struct nk_allocator alloc;
14879  alloc.userdata.ptr = 0;
14880  alloc.alloc = nk_malloc;
14881  alloc.free = nk_mfree;
14882  return nk_init(ctx, &alloc, font);
14883 }
14884 #endif
14885 NK_API int
14886 nk_init_fixed(struct nk_context *ctx, void *memory, nk_size size,
14887  const struct nk_user_font *font)
14888 {
14889  NK_ASSERT(memory);
14890  if (!memory) return 0;
14891  nk_setup(ctx, font);
14892  nk_buffer_init_fixed(&ctx->memory, memory, size);
14893  ctx->use_pool = nk_false;
14894  return 1;
14895 }
14896 NK_API int
14897 nk_init_custom(struct nk_context *ctx, struct nk_buffer *cmds,
14898  struct nk_buffer *pool, const struct nk_user_font *font)
14899 {
14900  NK_ASSERT(cmds);
14901  NK_ASSERT(pool);
14902  if (!cmds || !pool) return 0;
14903 
14904  nk_setup(ctx, font);
14905  ctx->memory = *cmds;
14906  if (pool->type == NK_BUFFER_FIXED) {
14907  /* take memory from buffer and alloc fixed pool */
14908  nk_pool_init_fixed(&ctx->pool, pool->memory.ptr, pool->memory.size);
14909  } else {
14910  /* create dynamic pool from buffer allocator */
14911  struct nk_allocator *alloc = &pool->pool;
14912  nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY);
14913  }
14914  ctx->use_pool = nk_true;
14915  return 1;
14916 }
14917 NK_API int
14918 nk_init(struct nk_context *ctx, struct nk_allocator *alloc,
14919  const struct nk_user_font *font)
14920 {
14921  NK_ASSERT(alloc);
14922  if (!alloc) return 0;
14923  nk_setup(ctx, font);
14924  nk_buffer_init(&ctx->memory, alloc, NK_DEFAULT_COMMAND_BUFFER_SIZE);
14925  nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY);
14926  ctx->use_pool = nk_true;
14927  return 1;
14928 }
14929 #ifdef NK_INCLUDE_COMMAND_USERDATA
14930 NK_API void
14931 nk_set_user_data(struct nk_context *ctx, nk_handle handle)
14932 {
14933  if (!ctx) return;
14934  ctx->userdata = handle;
14935  if (ctx->current)
14936  ctx->current->buffer.userdata = handle;
14937 }
14938 #endif
14939 NK_API void
14940 nk_free(struct nk_context *ctx)
14941 {
14942  NK_ASSERT(ctx);
14943  if (!ctx) return;
14944  nk_buffer_free(&ctx->memory);
14945  if (ctx->use_pool)
14946  nk_pool_free(&ctx->pool);
14947 
14948  nk_zero(&ctx->input, sizeof(ctx->input));
14949  nk_zero(&ctx->style, sizeof(ctx->style));
14950  nk_zero(&ctx->memory, sizeof(ctx->memory));
14951 
14952  ctx->seq = 0;
14953  ctx->build = 0;
14954  ctx->begin = 0;
14955  ctx->end = 0;
14956  ctx->active = 0;
14957  ctx->current = 0;
14958  ctx->freelist = 0;
14959  ctx->count = 0;
14960 }
14961 NK_API void
14962 nk_clear(struct nk_context *ctx)
14963 {
14964  struct nk_window *iter;
14965  struct nk_window *next;
14966  NK_ASSERT(ctx);
14967 
14968  if (!ctx) return;
14969  if (ctx->use_pool)
14970  nk_buffer_clear(&ctx->memory);
14971  else nk_buffer_reset(&ctx->memory, NK_BUFFER_FRONT);
14972 
14973  ctx->build = 0;
14974  ctx->memory.calls = 0;
14975  ctx->last_widget_state = 0;
14977  NK_MEMSET(&ctx->overlay, 0, sizeof(ctx->overlay));
14978 
14979  /* garbage collector */
14980  iter = ctx->begin;
14981  while (iter) {
14982  /* make sure valid minimized windows do not get removed */
14983  if ((iter->flags & NK_WINDOW_MINIMIZED) &&
14984  !(iter->flags & NK_WINDOW_CLOSED) &&
14985  iter->seq == ctx->seq) {
14986  iter = iter->next;
14987  continue;
14988  }
14989  /* remove hotness from hidden or closed windows*/
14990  if (((iter->flags & NK_WINDOW_HIDDEN) ||
14991  (iter->flags & NK_WINDOW_CLOSED)) &&
14992  iter == ctx->active) {
14993  ctx->active = iter->prev;
14994  ctx->end = iter->prev;
14995  if (!ctx->end)
14996  ctx->begin = 0;
14997  if (ctx->active)
14998  ctx->active->flags &= ~(unsigned)NK_WINDOW_ROM;
14999  }
15000  /* free unused popup windows */
15001  if (iter->popup.win && iter->popup.win->seq != ctx->seq) {
15002  nk_free_window(ctx, iter->popup.win);
15003  iter->popup.win = 0;
15004  }
15005  /* remove unused window state tables */
15006  {struct nk_table *n, *it = iter->tables;
15007  while (it) {
15008  n = it->next;
15009  if (it->seq != ctx->seq) {
15010  nk_remove_table(iter, it);
15011  nk_zero(it, sizeof(union nk_page_data));
15012  nk_free_table(ctx, it);
15013  if (it == iter->tables)
15014  iter->tables = n;
15015  } it = n;
15016  }}
15017  /* window itself is not used anymore so free */
15018  if (iter->seq != ctx->seq || iter->flags & NK_WINDOW_CLOSED) {
15019  next = iter->next;
15020  nk_remove_window(ctx, iter);
15021  nk_free_window(ctx, iter);
15022  iter = next;
15023  } else iter = iter->next;
15024  }
15025  ctx->seq++;
15026 }
15027 NK_LIB void
15028 nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer)
15029 {
15030  NK_ASSERT(ctx);
15031  NK_ASSERT(buffer);
15032  if (!ctx || !buffer) return;
15033  buffer->begin = ctx->memory.allocated;
15034  buffer->end = buffer->begin;
15035  buffer->last = buffer->begin;
15036  buffer->clip = nk_null_rect;
15037 }
15038 NK_LIB void
15039 nk_start(struct nk_context *ctx, struct nk_window *win)
15040 {
15041  NK_ASSERT(ctx);
15042  NK_ASSERT(win);
15043  nk_start_buffer(ctx, &win->buffer);
15044 }
15045 NK_LIB void
15046 nk_start_popup(struct nk_context *ctx, struct nk_window *win)
15047 {
15048  struct nk_popup_buffer *buf;
15049  NK_ASSERT(ctx);
15050  NK_ASSERT(win);
15051  if (!ctx || !win) return;
15052 
15053  /* save buffer fill state for popup */
15054  buf = &win->popup.buf;
15055  buf->begin = win->buffer.end;
15056  buf->end = win->buffer.end;
15057  buf->parent = win->buffer.last;
15058  buf->last = buf->begin;
15059  buf->active = nk_true;
15060 }
15061 NK_LIB void
15062 nk_finish_popup(struct nk_context *ctx, struct nk_window *win)
15063 {
15064  struct nk_popup_buffer *buf;
15065  NK_ASSERT(ctx);
15066  NK_ASSERT(win);
15067  if (!ctx || !win) return;
15068 
15069  buf = &win->popup.buf;
15070  buf->last = win->buffer.last;
15071  buf->end = win->buffer.end;
15072 }
15073 NK_LIB void
15074 nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer)
15075 {
15076  NK_ASSERT(ctx);
15077  NK_ASSERT(buffer);
15078  if (!ctx || !buffer) return;
15079  buffer->end = ctx->memory.allocated;
15080 }
15081 NK_LIB void
15082 nk_finish(struct nk_context *ctx, struct nk_window *win)
15083 {
15084  struct nk_popup_buffer *buf;
15085  struct nk_command *parent_last;
15086  void *memory;
15087 
15088  NK_ASSERT(ctx);
15089  NK_ASSERT(win);
15090  if (!ctx || !win) return;
15091  nk_finish_buffer(ctx, &win->buffer);
15092  if (!win->popup.buf.active) return;
15093 
15094  buf = &win->popup.buf;
15095  memory = ctx->memory.memory.ptr;
15096  parent_last = nk_ptr_add(struct nk_command, memory, buf->parent);
15097  parent_last->next = buf->end;
15098 }
15099 NK_LIB void
15100 nk_build(struct nk_context *ctx)
15101 {
15102  struct nk_window *it = 0;
15103  struct nk_command *cmd = 0;
15104  nk_byte *buffer = 0;
15105 
15106  /* draw cursor overlay */
15107  if (!ctx->style.cursor_active)
15109  if (ctx->style.cursor_active && !ctx->input.mouse.grabbed && ctx->style.cursor_visible) {
15110  struct nk_rect mouse_bounds;
15111  const struct nk_cursor *cursor = ctx->style.cursor_active;
15112  nk_command_buffer_init(&ctx->overlay, &ctx->memory, NK_CLIPPING_OFF);
15113  nk_start_buffer(ctx, &ctx->overlay);
15114 
15115  mouse_bounds.x = ctx->input.mouse.pos.x - cursor->offset.x;
15116  mouse_bounds.y = ctx->input.mouse.pos.y - cursor->offset.y;
15117  mouse_bounds.w = cursor->size.x;
15118  mouse_bounds.h = cursor->size.y;
15119 
15120  nk_draw_image(&ctx->overlay, mouse_bounds, &cursor->img, nk_white);
15121  nk_finish_buffer(ctx, &ctx->overlay);
15122  }
15123  /* build one big draw command list out of all window buffers */
15124  it = ctx->begin;
15125  buffer = (nk_byte*)ctx->memory.memory.ptr;
15126  while (it != 0) {
15127  struct nk_window *next = it->next;
15128  if (it->buffer.last == it->buffer.begin || (it->flags & NK_WINDOW_HIDDEN)||
15129  it->seq != ctx->seq)
15130  goto cont;
15131 
15132  cmd = nk_ptr_add(struct nk_command, buffer, it->buffer.last);
15133  while (next && ((next->buffer.last == next->buffer.begin) ||
15134  (next->flags & NK_WINDOW_HIDDEN) || next->seq != ctx->seq))
15135  next = next->next; /* skip empty command buffers */
15136 
15137  if (next) cmd->next = next->buffer.begin;
15138  cont: it = next;
15139  }
15140  /* append all popup draw commands into lists */
15141  it = ctx->begin;
15142  while (it != 0) {
15143  struct nk_window *next = it->next;
15144  struct nk_popup_buffer *buf;
15145  if (!it->popup.buf.active)
15146  goto skip;
15147 
15148  buf = &it->popup.buf;
15149  cmd->next = buf->begin;
15150  cmd = nk_ptr_add(struct nk_command, buffer, buf->last);
15151  buf->active = nk_false;
15152  skip: it = next;
15153  }
15154  if (cmd) {
15155  /* append overlay commands */
15156  if (ctx->overlay.end != ctx->overlay.begin)
15157  cmd->next = ctx->overlay.begin;
15158  else cmd->next = ctx->memory.allocated;
15159  }
15160 }
15161 NK_API const struct nk_command*
15162 nk__begin(struct nk_context *ctx)
15163 {
15164  struct nk_window *iter;
15165  nk_byte *buffer;
15166  NK_ASSERT(ctx);
15167  if (!ctx) return 0;
15168  if (!ctx->count) return 0;
15169 
15170  buffer = (nk_byte*)ctx->memory.memory.ptr;
15171  if (!ctx->build) {
15172  nk_build(ctx);
15173  ctx->build = nk_true;
15174  }
15175  iter = ctx->begin;
15176  while (iter && ((iter->buffer.begin == iter->buffer.end) ||
15177  (iter->flags & NK_WINDOW_HIDDEN) || iter->seq != ctx->seq))
15178  iter = iter->next;
15179  if (!iter) return 0;
15180  return nk_ptr_add_const(struct nk_command, buffer, iter->buffer.begin);
15181 }
15182 
15183 NK_API const struct nk_command*
15184 nk__next(struct nk_context *ctx, const struct nk_command *cmd)
15185 {
15186  nk_byte *buffer;
15187  const struct nk_command *next;
15188  NK_ASSERT(ctx);
15189  if (!ctx || !cmd || !ctx->count) return 0;
15190  if (cmd->next >= ctx->memory.allocated) return 0;
15191  buffer = (nk_byte*)ctx->memory.memory.ptr;
15192  next = nk_ptr_add_const(struct nk_command, buffer, cmd->next);
15193  return next;
15194 }
15195 
15196 
15197 
15198 
15199 
15200 
15201 /* ===============================================================
15202  *
15203  * POOL
15204  *
15205  * ===============================================================*/
15206 NK_LIB void
15207 nk_pool_init(struct nk_pool *pool, struct nk_allocator *alloc,
15208  unsigned int capacity)
15209 {
15210  nk_zero(pool, sizeof(*pool));
15211  pool->alloc = *alloc;
15212  pool->capacity = capacity;
15213  pool->type = NK_BUFFER_DYNAMIC;
15214  pool->pages = 0;
15215 }
15216 NK_LIB void
15217 nk_pool_free(struct nk_pool *pool)
15218 {
15219  struct nk_page *iter = pool->pages;
15220  if (!pool) return;
15221  if (pool->type == NK_BUFFER_FIXED) return;
15222  while (iter) {
15223  struct nk_page *next = iter->next;
15224  pool->alloc.free(pool->alloc.userdata, iter);
15225  iter = next;
15226  }
15227 }
15228 NK_LIB void
15229 nk_pool_init_fixed(struct nk_pool *pool, void *memory, nk_size size)
15230 {
15231  nk_zero(pool, sizeof(*pool));
15232  NK_ASSERT(size >= sizeof(struct nk_page));
15233  if (size < sizeof(struct nk_page)) return;
15234  pool->capacity = (unsigned)(size - sizeof(struct nk_page)) / sizeof(struct nk_page_element);
15235  pool->pages = (struct nk_page*)memory;
15236  pool->type = NK_BUFFER_FIXED;
15237  pool->size = size;
15238 }
15239 NK_LIB struct nk_page_element*
15240 nk_pool_alloc(struct nk_pool *pool)
15241 {
15242  if (!pool->pages || pool->pages->size >= pool->capacity) {
15243  /* allocate new page */
15244  struct nk_page *page;
15245  if (pool->type == NK_BUFFER_FIXED) {
15246  NK_ASSERT(pool->pages);
15247  if (!pool->pages) return 0;
15248  NK_ASSERT(pool->pages->size < pool->capacity);
15249  return 0;
15250  } else {
15251  nk_size size = sizeof(struct nk_page);
15252  size += NK_POOL_DEFAULT_CAPACITY * sizeof(union nk_page_data);
15253  page = (struct nk_page*)pool->alloc.alloc(pool->alloc.userdata,0, size);
15254  page->next = pool->pages;
15255  pool->pages = page;
15256  page->size = 0;
15257  }
15258  } return &pool->pages->win[pool->pages->size++];
15259 }
15260 
15261 
15262 
15263 
15264 
15265 /* ===============================================================
15266  *
15267  * PAGE ELEMENT
15268  *
15269  * ===============================================================*/
15270 NK_LIB struct nk_page_element*
15271 nk_create_page_element(struct nk_context *ctx)
15272 {
15273  struct nk_page_element *elem;
15274  if (ctx->freelist) {
15275  /* unlink page element from free list */
15276  elem = ctx->freelist;
15277  ctx->freelist = elem->next;
15278  } else if (ctx->use_pool) {
15279  /* allocate page element from memory pool */
15280  elem = nk_pool_alloc(&ctx->pool);
15281  NK_ASSERT(elem);
15282  if (!elem) return 0;
15283  } else {
15284  /* allocate new page element from back of fixed size memory buffer */
15285  NK_STORAGE const nk_size size = sizeof(struct nk_page_element);
15286  NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_page_element);
15287  elem = (struct nk_page_element*)nk_buffer_alloc(&ctx->memory, NK_BUFFER_BACK, size, align);
15288  NK_ASSERT(elem);
15289  if (!elem) return 0;
15290  }
15291  nk_zero_struct(*elem);
15292  elem->next = 0;
15293  elem->prev = 0;
15294  return elem;
15295 }
15296 NK_LIB void
15297 nk_link_page_element_into_freelist(struct nk_context *ctx,
15298  struct nk_page_element *elem)
15299 {
15300  /* link table into freelist */
15301  if (!ctx->freelist) {
15302  ctx->freelist = elem;
15303  } else {
15304  elem->next = ctx->freelist;
15305  ctx->freelist = elem;
15306  }
15307 }
15308 NK_LIB void
15309 nk_free_page_element(struct nk_context *ctx, struct nk_page_element *elem)
15310 {
15311  /* we have a pool so just add to free list */
15312  if (ctx->use_pool) {
15313  nk_link_page_element_into_freelist(ctx, elem);
15314  return;
15315  }
15316  /* if possible remove last element from back of fixed memory buffer */
15317  {void *elem_end = (void*)(elem + 1);
15318  void *buffer_end = (nk_byte*)ctx->memory.memory.ptr + ctx->memory.size;
15319  if (elem_end == buffer_end)
15320  ctx->memory.size -= sizeof(struct nk_page_element);
15321  else nk_link_page_element_into_freelist(ctx, elem);}
15322 }
15323 
15324 
15325 
15326 
15327 
15328 /* ===============================================================
15329  *
15330  * TABLE
15331  *
15332  * ===============================================================*/
15333 NK_LIB struct nk_table*
15334 nk_create_table(struct nk_context *ctx)
15335 {
15336  struct nk_page_element *elem;
15337  elem = nk_create_page_element(ctx);
15338  if (!elem) return 0;
15339  nk_zero_struct(*elem);
15340  return &elem->data.tbl;
15341 }
15342 NK_LIB void
15343 nk_free_table(struct nk_context *ctx, struct nk_table *tbl)
15344 {
15345  union nk_page_data *pd = NK_CONTAINER_OF(tbl, union nk_page_data, tbl);
15346  struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
15347  nk_free_page_element(ctx, pe);
15348 }
15349 NK_LIB void
15350 nk_push_table(struct nk_window *win, struct nk_table *tbl)
15351 {
15352  if (!win->tables) {
15353  win->tables = tbl;
15354  tbl->next = 0;
15355  tbl->prev = 0;
15356  tbl->size = 0;
15357  win->table_count = 1;
15358  return;
15359  }
15360  win->tables->prev = tbl;
15361  tbl->next = win->tables;
15362  tbl->prev = 0;
15363  tbl->size = 0;
15364  win->tables = tbl;
15365  win->table_count++;
15366 }
15367 NK_LIB void
15368 nk_remove_table(struct nk_window *win, struct nk_table *tbl)
15369 {
15370  if (win->tables == tbl)
15371  win->tables = tbl->next;
15372  if (tbl->next)
15373  tbl->next->prev = tbl->prev;
15374  if (tbl->prev)
15375  tbl->prev->next = tbl->next;
15376  tbl->next = 0;
15377  tbl->prev = 0;
15378 }
15379 NK_LIB nk_uint*
15380 nk_add_value(struct nk_context *ctx, struct nk_window *win,
15381  nk_hash name, nk_uint value)
15382 {
15383  NK_ASSERT(ctx);
15384  NK_ASSERT(win);
15385  if (!win || !ctx) return 0;
15386  if (!win->tables || win->tables->size >= NK_VALUE_PAGE_CAPACITY) {
15387  struct nk_table *tbl = nk_create_table(ctx);
15388  NK_ASSERT(tbl);
15389  if (!tbl) return 0;
15390  nk_push_table(win, tbl);
15391  }
15392  win->tables->seq = win->seq;
15393  win->tables->keys[win->tables->size] = name;
15394  win->tables->values[win->tables->size] = value;
15395  return &win->tables->values[win->tables->size++];
15396 }
15397 NK_LIB nk_uint*
15398 nk_find_value(struct nk_window *win, nk_hash name)
15399 {
15400  struct nk_table *iter = win->tables;
15401  while (iter) {
15402  unsigned int i = 0;
15403  unsigned int size = iter->size;
15404  for (i = 0; i < size; ++i) {
15405  if (iter->keys[i] == name) {
15406  iter->seq = win->seq;
15407  return &iter->values[i];
15408  }
15410  iter = iter->next;
15411  }
15412  return 0;
15413 }
15414 
15415 
15416 
15417 
15418 
15419 /* ===============================================================
15420  *
15421  * PANEL
15422  *
15423  * ===============================================================*/
15424 NK_LIB void*
15425 nk_create_panel(struct nk_context *ctx)
15426 {
15427  struct nk_page_element *elem;
15428  elem = nk_create_page_element(ctx);
15429  if (!elem) return 0;
15430  nk_zero_struct(*elem);
15431  return &elem->data.pan;
15432 }
15433 NK_LIB void
15434 nk_free_panel(struct nk_context *ctx, struct nk_panel *pan)
15435 {
15436  union nk_page_data *pd = NK_CONTAINER_OF(pan, union nk_page_data, pan);
15437  struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
15438  nk_free_page_element(ctx, pe);
15439 }
15440 NK_LIB int
15441 nk_panel_has_header(nk_flags flags, const char *title)
15442 {
15443  int active = 0;
15444  active = (flags & (NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE));
15445  active = active || (flags & NK_WINDOW_TITLE);
15446  active = active && !(flags & NK_WINDOW_HIDDEN) && title;
15447  return active;
15448 }
15449 NK_LIB struct nk_vec2
15450 nk_panel_get_padding(const struct nk_style *style, enum nk_panel_type type)
15451 {
15452  switch (type) {
15453  default:
15454  case NK_PANEL_WINDOW: return style->window.padding;
15455  case NK_PANEL_GROUP: return style->window.group_padding;
15456  case NK_PANEL_POPUP: return style->window.popup_padding;
15457  case NK_PANEL_CONTEXTUAL: return style->window.contextual_padding;
15458  case NK_PANEL_COMBO: return style->window.combo_padding;
15459  case NK_PANEL_MENU: return style->window.menu_padding;
15460  case NK_PANEL_TOOLTIP: return style->window.menu_padding;}
15461 }
15462 NK_LIB float
15463 nk_panel_get_border(const struct nk_style *style, nk_flags flags,
15464  enum nk_panel_type type)
15465 {
15466  if (flags & NK_WINDOW_BORDER) {
15467  switch (type) {
15468  default:
15469  case NK_PANEL_WINDOW: return style->window.border;
15470  case NK_PANEL_GROUP: return style->window.group_border;
15471  case NK_PANEL_POPUP: return style->window.popup_border;
15472  case NK_PANEL_CONTEXTUAL: return style->window.contextual_border;
15473  case NK_PANEL_COMBO: return style->window.combo_border;
15474  case NK_PANEL_MENU: return style->window.menu_border;
15475  case NK_PANEL_TOOLTIP: return style->window.menu_border;
15476  }} else return 0;
15477 }
15478 NK_LIB struct nk_color
15479 nk_panel_get_border_color(const struct nk_style *style, enum nk_panel_type type)
15480 {
15481  switch (type) {
15482  default:
15483  case NK_PANEL_WINDOW: return style->window.border_color;
15484  case NK_PANEL_GROUP: return style->window.group_border_color;
15485  case NK_PANEL_POPUP: return style->window.popup_border_color;
15486  case NK_PANEL_CONTEXTUAL: return style->window.contextual_border_color;
15487  case NK_PANEL_COMBO: return style->window.combo_border_color;
15488  case NK_PANEL_MENU: return style->window.menu_border_color;
15489  case NK_PANEL_TOOLTIP: return style->window.menu_border_color;}
15490 }
15491 NK_LIB int
15492 nk_panel_is_sub(enum nk_panel_type type)
15493 {
15494  return (type & NK_PANEL_SET_SUB)?1:0;
15495 }
15496 NK_LIB int
15497 nk_panel_is_nonblock(enum nk_panel_type type)
15498 {
15499  return (type & NK_PANEL_SET_NONBLOCK)?1:0;
15500 }
15501 NK_LIB int
15502 nk_panel_begin(struct nk_context *ctx, const char *title, enum nk_panel_type panel_type)
15503 {
15504  struct nk_input *in;
15505  struct nk_window *win;
15506  struct nk_panel *layout;
15507  struct nk_command_buffer *out;
15508  const struct nk_style *style;
15509  const struct nk_user_font *font;
15510 
15511  struct nk_vec2 scrollbar_size;
15512  struct nk_vec2 panel_padding;
15513 
15514  NK_ASSERT(ctx);
15515  NK_ASSERT(ctx->current);
15516  NK_ASSERT(ctx->current->layout);
15517  if (!ctx || !ctx->current || !ctx->current->layout) return 0;
15518  nk_zero(ctx->current->layout, sizeof(*ctx->current->layout));
15519  if ((ctx->current->flags & NK_WINDOW_HIDDEN) || (ctx->current->flags & NK_WINDOW_CLOSED)) {
15520  nk_zero(ctx->current->layout, sizeof(struct nk_panel));
15521  ctx->current->layout->type = panel_type;
15522  return 0;
15523  }
15524  /* pull state into local stack */
15525  style = &ctx->style;
15526  font = style->font;
15527  win = ctx->current;
15528  layout = win->layout;
15529  out = &win->buffer;
15530  in = (win->flags & NK_WINDOW_NO_INPUT) ? 0: &ctx->input;
15531 #ifdef NK_INCLUDE_COMMAND_USERDATA
15532  win->buffer.userdata = ctx->userdata;
15533 #endif
15534  /* pull style configuration into local stack */
15535  scrollbar_size = style->window.scrollbar_size;
15536  panel_padding = nk_panel_get_padding(style, panel_type);
15537 
15538  /* window movement */
15539  if ((win->flags & NK_WINDOW_MOVABLE) && !(win->flags & NK_WINDOW_ROM)) {
15540  int left_mouse_down;
15541  int left_mouse_click_in_cursor;
15542 
15543  /* calculate draggable window space */
15544  struct nk_rect header;
15545  header.x = win->bounds.x;
15546  header.y = win->bounds.y;
15547  header.w = win->bounds.w;
15548  if (nk_panel_has_header(win->flags, title)) {
15549  header.h = font->height + 2.0f * style->window.header.padding.y;
15550  header.h += 2.0f * style->window.header.label_padding.y;
15551  } else header.h = panel_padding.y;
15552 
15553  /* window movement by dragging */
15554  left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
15555  left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
15556  NK_BUTTON_LEFT, header, nk_true);
15557  if (left_mouse_down && left_mouse_click_in_cursor) {
15558  win->bounds.x = win->bounds.x + in->mouse.delta.x;
15559  win->bounds.y = win->bounds.y + in->mouse.delta.y;
15563  }
15564  }
15565 
15566  /* setup panel */
15567  layout->type = panel_type;
15568  layout->flags = win->flags;
15569  layout->bounds = win->bounds;
15570  layout->bounds.x += panel_padding.x;
15571  layout->bounds.w -= 2*panel_padding.x;
15572  if (win->flags & NK_WINDOW_BORDER) {
15573  layout->border = nk_panel_get_border(style, win->flags, panel_type);
15574  layout->bounds = nk_shrink_rect(layout->bounds, layout->border);
15575  } else layout->border = 0;
15576  layout->at_y = layout->bounds.y;
15577  layout->at_x = layout->bounds.x;
15578  layout->max_x = 0;
15579  layout->header_height = 0;
15580  layout->footer_height = 0;
15582  layout->row.index = 0;
15583  layout->row.columns = 0;
15584  layout->row.ratio = 0;
15585  layout->row.item_width = 0;
15586  layout->row.tree_depth = 0;
15587  layout->row.height = panel_padding.y;
15588  layout->has_scrolling = nk_true;
15589  if (!(win->flags & NK_WINDOW_NO_SCROLLBAR))
15590  layout->bounds.w -= scrollbar_size.x;
15591  if (!nk_panel_is_nonblock(panel_type)) {
15592  layout->footer_height = 0;
15593  if (!(win->flags & NK_WINDOW_NO_SCROLLBAR) || win->flags & NK_WINDOW_SCALABLE)
15594  layout->footer_height = scrollbar_size.y;
15595  layout->bounds.h -= layout->footer_height;
15596  }
15597 
15598  /* panel header */
15599  if (nk_panel_has_header(win->flags, title))
15600  {
15601  struct nk_text text;
15602  struct nk_rect header;
15603  const struct nk_style_item *background = 0;
15604 
15605  /* calculate header bounds */
15606  header.x = win->bounds.x;
15607  header.y = win->bounds.y;
15608  header.w = win->bounds.w;
15609  header.h = font->height + 2.0f * style->window.header.padding.y;
15610  header.h += (2.0f * style->window.header.label_padding.y);
15611 
15612  /* shrink panel by header */
15613  layout->header_height = header.h;
15614  layout->bounds.y += header.h;
15615  layout->bounds.h -= header.h;
15616  layout->at_y += header.h;
15617 
15618  /* select correct header background and text color */
15619  if (ctx->active == win) {
15620  background = &style->window.header.active;
15621  text.text = style->window.header.label_active;
15622  } else if (nk_input_is_mouse_hovering_rect(&ctx->input, header)) {
15623  background = &style->window.header.hover;
15624  text.text = style->window.header.label_hover;
15625  } else {
15626  background = &style->window.header.normal;
15627  text.text = style->window.header.label_normal;
15628  }
15629 
15630  /* draw header background */
15631  header.h += 1.0f;
15632  if (background->type == NK_STYLE_ITEM_IMAGE) {
15633  text.background = nk_rgba(0,0,0,0);
15634  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
15635  } else {
15636  text.background = background->data.color;
15637  nk_fill_rect(out, header, 0, background->data.color);
15638  }
15639 
15640  /* window close button */
15641  {struct nk_rect button;
15642  button.y = header.y + style->window.header.padding.y;
15643  button.h = header.h - 2 * style->window.header.padding.y;
15644  button.w = button.h;
15645  if (win->flags & NK_WINDOW_CLOSABLE) {
15646  nk_flags ws = 0;
15647  if (style->window.header.align == NK_HEADER_RIGHT) {
15648  button.x = (header.w + header.x) - (button.w + style->window.header.padding.x);
15649  header.w -= button.w + style->window.header.spacing.x + style->window.header.padding.x;
15650  } else {
15651  button.x = header.x + style->window.header.padding.x;
15652  header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x;
15653  }
15654 
15655  if (nk_do_button_symbol(&ws, &win->buffer, button,
15657  &style->window.header.close_button, in, style->font) && !(win->flags & NK_WINDOW_ROM))
15658  {
15659  layout->flags |= NK_WINDOW_HIDDEN;
15660  layout->flags &= (nk_flags)~NK_WINDOW_MINIMIZED;
15661  }
15662  }
15663 
15664  /* window minimize button */
15665  if (win->flags & NK_WINDOW_MINIMIZABLE) {
15666  nk_flags ws = 0;
15667  if (style->window.header.align == NK_HEADER_RIGHT) {
15668  button.x = (header.w + header.x) - button.w;
15669  if (!(win->flags & NK_WINDOW_CLOSABLE)) {
15670  button.x -= style->window.header.padding.x;
15671  header.w -= style->window.header.padding.x;
15672  }
15673  header.w -= button.w + style->window.header.spacing.x;
15674  } else {
15675  button.x = header.x;
15676  header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x;
15677  }
15678  if (nk_do_button_symbol(&ws, &win->buffer, button, (layout->flags & NK_WINDOW_MINIMIZED)?
15680  NK_BUTTON_DEFAULT, &style->window.header.minimize_button, in, style->font) && !(win->flags & NK_WINDOW_ROM))
15681  layout->flags = (layout->flags & NK_WINDOW_MINIMIZED) ?
15682  layout->flags & (nk_flags)~NK_WINDOW_MINIMIZED:
15683  layout->flags | NK_WINDOW_MINIMIZED;
15684  }}
15685 
15686  {/* window header title */
15687  int text_len = nk_strlen(title);
15688  struct nk_rect label = {0,0,0,0};
15689  float t = font->width(font->userdata, font->height, title, text_len);
15690  text.padding = nk_vec2(0,0);
15691 
15692  label.x = header.x + style->window.header.padding.x;
15693  label.x += style->window.header.label_padding.x;
15694  label.y = header.y + style->window.header.label_padding.y;
15695  label.h = font->height + 2 * style->window.header.label_padding.y;
15696  label.w = t + 2 * style->window.header.spacing.x;
15697  label.w = NK_CLAMP(0, label.w, header.x + header.w - label.x);
15698  nk_widget_text(out, label,(const char*)title, text_len, &text, NK_TEXT_LEFT, font);}
15699  }
15700 
15701  /* draw window background */
15702  if (!(layout->flags & NK_WINDOW_MINIMIZED) && !(layout->flags & NK_WINDOW_DYNAMIC)) {
15703  struct nk_rect body;
15704  body.x = win->bounds.x;
15705  body.w = win->bounds.w;
15706  body.y = (win->bounds.y + layout->header_height);
15707  body.h = (win->bounds.h - layout->header_height);
15709  nk_draw_image(out, body, &style->window.fixed_background.data.image, nk_white);
15710  else nk_fill_rect(out, body, 0, style->window.fixed_background.data.color);
15711  }
15712 
15713  /* set clipping rectangle */
15714  {struct nk_rect clip;
15715  layout->clip = layout->bounds;
15716  nk_unify(&clip, &win->buffer.clip, layout->clip.x, layout->clip.y,
15717  layout->clip.x + layout->clip.w, layout->clip.y + layout->clip.h);
15718  nk_push_scissor(out, clip);
15719  layout->clip = clip;}
15720  return !(layout->flags & NK_WINDOW_HIDDEN) && !(layout->flags & NK_WINDOW_MINIMIZED);
15721 }
15722 NK_LIB void
15723 nk_panel_end(struct nk_context *ctx)
15724 {
15725  struct nk_input *in;
15726  struct nk_window *window;
15727  struct nk_panel *layout;
15728  const struct nk_style *style;
15729  struct nk_command_buffer *out;
15730 
15731  struct nk_vec2 scrollbar_size;
15732  struct nk_vec2 panel_padding;
15733 
15734  NK_ASSERT(ctx);
15735  NK_ASSERT(ctx->current);
15736  NK_ASSERT(ctx->current->layout);
15737  if (!ctx || !ctx->current || !ctx->current->layout)
15738  return;
15739 
15740  window = ctx->current;
15741  layout = window->layout;
15742  style = &ctx->style;
15743  out = &window->buffer;
15744  in = (layout->flags & NK_WINDOW_ROM || layout->flags & NK_WINDOW_NO_INPUT) ? 0 :&ctx->input;
15745  if (!nk_panel_is_sub(layout->type))
15746  nk_push_scissor(out, nk_null_rect);
15747 
15748  /* cache configuration data */
15749  scrollbar_size = style->window.scrollbar_size;
15750  panel_padding = nk_panel_get_padding(style, layout->type);
15751 
15752  /* update the current cursor Y-position to point over the last added widget */
15753  layout->at_y += layout->row.height;
15754 
15755  /* dynamic panels */
15756  if (layout->flags & NK_WINDOW_DYNAMIC && !(layout->flags & NK_WINDOW_MINIMIZED))
15757  {
15758  /* update panel height to fit dynamic growth */
15759  struct nk_rect empty_space;
15760  if (layout->at_y < (layout->bounds.y + layout->bounds.h))
15761  layout->bounds.h = layout->at_y - layout->bounds.y;
15762 
15763  /* fill top empty space */
15764  empty_space.x = window->bounds.x;
15765  empty_space.y = layout->bounds.y;
15766  empty_space.h = panel_padding.y;
15767  empty_space.w = window->bounds.w;
15768  nk_fill_rect(out, empty_space, 0, style->window.background);
15769 
15770  /* fill left empty space */
15771  empty_space.x = window->bounds.x;
15772  empty_space.y = layout->bounds.y;
15773  empty_space.w = panel_padding.x + layout->border;
15774  empty_space.h = layout->bounds.h;
15775  nk_fill_rect(out, empty_space, 0, style->window.background);
15776 
15777  /* fill right empty space */
15778  empty_space.x = layout->bounds.x + layout->bounds.w - layout->border;
15779  empty_space.y = layout->bounds.y;
15780  empty_space.w = panel_padding.x + layout->border;
15781  empty_space.h = layout->bounds.h;
15782  if (*layout->offset_y == 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR))
15783  empty_space.w += scrollbar_size.x;
15784  nk_fill_rect(out, empty_space, 0, style->window.background);
15785 
15786  /* fill bottom empty space */
15787  if (*layout->offset_x != 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR)) {
15788  empty_space.x = window->bounds.x;
15789  empty_space.y = layout->bounds.y + layout->bounds.h;
15790  empty_space.w = window->bounds.w;
15791  empty_space.h = scrollbar_size.y;
15792  nk_fill_rect(out, empty_space, 0, style->window.background);
15793  }
15794  }
15795 
15796  /* scrollbars */
15797  if (!(layout->flags & NK_WINDOW_NO_SCROLLBAR) &&
15798  !(layout->flags & NK_WINDOW_MINIMIZED) &&
15800  {
15801  struct nk_rect scroll;
15802  int scroll_has_scrolling;
15803  float scroll_target;
15804  float scroll_offset;
15805  float scroll_step;
15806  float scroll_inc;
15807 
15808  /* mouse wheel scrolling */
15809  if (nk_panel_is_sub(layout->type))
15810  {
15811  /* sub-window mouse wheel scrolling */
15812  struct nk_window *root_window = window;
15813  struct nk_panel *root_panel = window->layout;
15814  while (root_panel->parent)
15815  root_panel = root_panel->parent;
15816  while (root_window->parent)
15817  root_window = root_window->parent;
15818 
15819  /* only allow scrolling if parent window is active */
15820  scroll_has_scrolling = 0;
15821  if ((root_window == ctx->active) && layout->has_scrolling) {
15822  /* and panel is being hovered and inside clip rect*/
15823  if (nk_input_is_mouse_hovering_rect(in, layout->bounds) &&
15824  NK_INTERSECT(layout->bounds.x, layout->bounds.y, layout->bounds.w, layout->bounds.h,
15825  root_panel->clip.x, root_panel->clip.y, root_panel->clip.w, root_panel->clip.h))
15826  {
15827  /* deactivate all parent scrolling */
15828  root_panel = window->layout;
15829  while (root_panel->parent) {
15830  root_panel->has_scrolling = nk_false;
15831  root_panel = root_panel->parent;
15832  }
15833  root_panel->has_scrolling = nk_false;
15834  scroll_has_scrolling = nk_true;
15835  }
15836  }
15837  } else if (!nk_panel_is_sub(layout->type)) {
15838  /* window mouse wheel scrolling */
15839  scroll_has_scrolling = (window == ctx->active) && layout->has_scrolling;
15840  if (in && (in->mouse.scroll_delta.y > 0 || in->mouse.scroll_delta.x > 0) && scroll_has_scrolling)
15841  window->scrolled = nk_true;
15842  else window->scrolled = nk_false;
15843  } else scroll_has_scrolling = nk_false;
15844 
15845  {
15846  /* vertical scrollbar */
15847  nk_flags state = 0;
15848  scroll.x = layout->bounds.x + layout->bounds.w + panel_padding.x;
15849  scroll.y = layout->bounds.y;
15850  scroll.w = scrollbar_size.x;
15851  scroll.h = layout->bounds.h;
15852 
15853  scroll_offset = (float)*layout->offset_y;
15854  scroll_step = scroll.h * 0.10f;
15855  scroll_inc = scroll.h * 0.01f;
15856  scroll_target = (float)(int)(layout->at_y - scroll.y);
15857  scroll_offset = nk_do_scrollbarv(&state, out, scroll, scroll_has_scrolling,
15858  scroll_offset, scroll_target, scroll_step, scroll_inc,
15859  &ctx->style.scrollv, in, style->font);
15860  *layout->offset_y = (nk_uint)scroll_offset;
15861  if (in && scroll_has_scrolling)
15862  in->mouse.scroll_delta.y = 0;
15863  }
15864  {
15865  /* horizontal scrollbar */
15866  nk_flags state = 0;
15867  scroll.x = layout->bounds.x;
15868  scroll.y = layout->bounds.y + layout->bounds.h;
15869  scroll.w = layout->bounds.w;
15870  scroll.h = scrollbar_size.y;
15871 
15872  scroll_offset = (float)*layout->offset_x;
15873  scroll_target = (float)(int)(layout->max_x - scroll.x);
15874  scroll_step = layout->max_x * 0.05f;
15875  scroll_inc = layout->max_x * 0.005f;
15876  scroll_offset = nk_do_scrollbarh(&state, out, scroll, scroll_has_scrolling,
15877  scroll_offset, scroll_target, scroll_step, scroll_inc,
15878  &ctx->style.scrollh, in, style->font);
15879  *layout->offset_x = (nk_uint)scroll_offset;
15880  }
15881  }
15882 
15883  /* hide scroll if no user input */
15884  if (window->flags & NK_WINDOW_SCROLL_AUTO_HIDE) {
15885  int has_input = ctx->input.mouse.delta.x != 0 || ctx->input.mouse.delta.y != 0 || ctx->input.mouse.scroll_delta.y != 0;
15886  int is_window_hovered = nk_window_is_hovered(ctx);
15887  int any_item_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED);
15888  if ((!has_input && is_window_hovered) || (!is_window_hovered && !any_item_active))
15890  else window->scrollbar_hiding_timer = 0;
15891  } else window->scrollbar_hiding_timer = 0;
15892 
15893  /* window border */
15894  if (layout->flags & NK_WINDOW_BORDER)
15895  {
15896  struct nk_color border_color = nk_panel_get_border_color(style, layout->type);
15897  const float padding_y = (layout->flags & NK_WINDOW_MINIMIZED)
15898  ? (style->window.border + window->bounds.y + layout->header_height)
15899  : ((layout->flags & NK_WINDOW_DYNAMIC)
15900  ? (layout->bounds.y + layout->bounds.h + layout->footer_height)
15901  : (window->bounds.y + window->bounds.h));
15902  struct nk_rect b = window->bounds;
15903  b.h = padding_y - window->bounds.y;
15904  nk_stroke_rect(out, b, 0, layout->border, border_color);
15905  }
15906 
15907  /* scaler */
15908  if ((layout->flags & NK_WINDOW_SCALABLE) && in && !(layout->flags & NK_WINDOW_MINIMIZED))
15909  {
15910  /* calculate scaler bounds */
15911  struct nk_rect scaler;
15912  scaler.w = scrollbar_size.x;
15913  scaler.h = scrollbar_size.y;
15914  scaler.y = layout->bounds.y + layout->bounds.h;
15915  if (layout->flags & NK_WINDOW_SCALE_LEFT)
15916  scaler.x = layout->bounds.x - panel_padding.x * 0.5f;
15917  else scaler.x = layout->bounds.x + layout->bounds.w + panel_padding.x;
15918  if (layout->flags & NK_WINDOW_NO_SCROLLBAR)
15919  scaler.x -= scaler.w;
15920 
15921  /* draw scaler */
15922  {const struct nk_style_item *item = &style->window.scaler;
15923  if (item->type == NK_STYLE_ITEM_IMAGE)
15924  nk_draw_image(out, scaler, &item->data.image, nk_white);
15925  else {
15926  if (layout->flags & NK_WINDOW_SCALE_LEFT) {
15927  nk_fill_triangle(out, scaler.x, scaler.y, scaler.x,
15928  scaler.y + scaler.h, scaler.x + scaler.w,
15929  scaler.y + scaler.h, item->data.color);
15930  } else {
15931  nk_fill_triangle(out, scaler.x + scaler.w, scaler.y, scaler.x + scaler.w,
15932  scaler.y + scaler.h, scaler.x, scaler.y + scaler.h, item->data.color);
15933  }
15934  }}
15935 
15936  /* do window scaling */
15937  if (!(window->flags & NK_WINDOW_ROM)) {
15938  struct nk_vec2 window_size = style->window.min_size;
15939  int left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
15940  int left_mouse_click_in_scaler = nk_input_has_mouse_click_down_in_rect(in,
15941  NK_BUTTON_LEFT, scaler, nk_true);
15942 
15943  if (left_mouse_down && left_mouse_click_in_scaler) {
15944  float delta_x = in->mouse.delta.x;
15945  if (layout->flags & NK_WINDOW_SCALE_LEFT) {
15946  delta_x = -delta_x;
15947  window->bounds.x += in->mouse.delta.x;
15948  }
15949  /* dragging in x-direction */
15950  if (window->bounds.w + delta_x >= window_size.x) {
15951  if ((delta_x < 0) || (delta_x > 0 && in->mouse.pos.x >= scaler.x)) {
15952  window->bounds.w = window->bounds.w + delta_x;
15953  scaler.x += in->mouse.delta.x;
15954  }
15955  }
15956  /* dragging in y-direction (only possible if static window) */
15957  if (!(layout->flags & NK_WINDOW_DYNAMIC)) {
15958  if (window_size.y < window->bounds.h + in->mouse.delta.y) {
15959  if ((in->mouse.delta.y < 0) || (in->mouse.delta.y > 0 && in->mouse.pos.y >= scaler.y)) {
15960  window->bounds.h = window->bounds.h + in->mouse.delta.y;
15961  scaler.y += in->mouse.delta.y;
15962  }
15963  }
15964  }
15966  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = scaler.x + scaler.w/2.0f;
15967  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = scaler.y + scaler.h/2.0f;
15968  }
15969  }
15970  }
15971  if (!nk_panel_is_sub(layout->type)) {
15972  /* window is hidden so clear command buffer */
15973  if (layout->flags & NK_WINDOW_HIDDEN)
15974  nk_command_buffer_reset(&window->buffer);
15975  /* window is visible and not tab */
15976  else nk_finish(ctx, window);
15977  }
15978 
15979  /* NK_WINDOW_REMOVE_ROM flag was set so remove NK_WINDOW_ROM */
15980  if (layout->flags & NK_WINDOW_REMOVE_ROM) {
15981  layout->flags &= ~(nk_flags)NK_WINDOW_ROM;
15982  layout->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM;
15983  }
15984  window->flags = layout->flags;
15985 
15986  /* property garbage collector */
15987  if (window->property.active && window->property.old != window->property.seq &&
15988  window->property.active == window->property.prev) {
15989  nk_zero(&window->property, sizeof(window->property));
15990  } else {
15991  window->property.old = window->property.seq;
15992  window->property.prev = window->property.active;
15993  window->property.seq = 0;
15994  }
15995  /* edit garbage collector */
15996  if (window->edit.active && window->edit.old != window->edit.seq &&
15997  window->edit.active == window->edit.prev) {
15998  nk_zero(&window->edit, sizeof(window->edit));
15999  } else {
16000  window->edit.old = window->edit.seq;
16001  window->edit.prev = window->edit.active;
16002  window->edit.seq = 0;
16003  }
16004  /* contextual garbage collector */
16005  if (window->popup.active_con && window->popup.con_old != window->popup.con_count) {
16006  window->popup.con_count = 0;
16007  window->popup.con_old = 0;
16008  window->popup.active_con = 0;
16009  } else {
16010  window->popup.con_old = window->popup.con_count;
16011  window->popup.con_count = 0;
16012  }
16013  window->popup.combo_count = 0;
16014  /* helper to make sure you have a 'nk_tree_push' for every 'nk_tree_pop' */
16015  NK_ASSERT(!layout->row.tree_depth);
16016 }
16017 
16018 
16019 
16020 
16021 
16022 /* ===============================================================
16023  *
16024  * WINDOW
16025  *
16026  * ===============================================================*/
16027 NK_LIB void*
16028 nk_create_window(struct nk_context *ctx)
16029 {
16030  struct nk_page_element *elem;
16031  elem = nk_create_page_element(ctx);
16032  if (!elem) return 0;
16033  elem->data.win.seq = ctx->seq;
16034  return &elem->data.win;
16035 }
16036 NK_LIB void
16037 nk_free_window(struct nk_context *ctx, struct nk_window *win)
16038 {
16039  /* unlink windows from list */
16040  struct nk_table *it = win->tables;
16041  if (win->popup.win) {
16042  nk_free_window(ctx, win->popup.win);
16043  win->popup.win = 0;
16044  }
16045  win->next = 0;
16046  win->prev = 0;
16047 
16048  while (it) {
16049  /*free window state tables */
16050  struct nk_table *n = it->next;
16051  nk_remove_table(win, it);
16052  nk_free_table(ctx, it);
16053  if (it == win->tables)
16054  win->tables = n;
16055  it = n;
16056  }
16057 
16058  /* link windows into freelist */
16059  {union nk_page_data *pd = NK_CONTAINER_OF(win, union nk_page_data, win);
16060  struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
16061  nk_free_page_element(ctx, pe);}
16062 }
16063 NK_LIB struct nk_window*
16064 nk_find_window(struct nk_context *ctx, nk_hash hash, const char *name)
16065 {
16066  struct nk_window *iter;
16067  iter = ctx->begin;
16068  while (iter) {
16069  NK_ASSERT(iter != iter->next);
16070  if (iter->name == hash) {
16071  int max_len = nk_strlen(iter->name_string);
16072  if (!nk_stricmpn(iter->name_string, name, max_len))
16073  return iter;
16074  }
16075  iter = iter->next;
16076  }
16077  return 0;
16078 }
16079 NK_LIB void
16080 nk_insert_window(struct nk_context *ctx, struct nk_window *win,
16081  enum nk_window_insert_location loc)
16082 {
16083  const struct nk_window *iter;
16084  NK_ASSERT(ctx);
16085  NK_ASSERT(win);
16086  if (!win || !ctx) return;
16087 
16088  iter = ctx->begin;
16089  while (iter) {
16090  NK_ASSERT(iter != iter->next);
16091  NK_ASSERT(iter != win);
16092  if (iter == win) return;
16093  iter = iter->next;
16094  }
16095 
16096  if (!ctx->begin) {
16097  win->next = 0;
16098  win->prev = 0;
16099  ctx->begin = win;
16100  ctx->end = win;
16101  ctx->count = 1;
16102  return;
16103  }
16104  if (loc == NK_INSERT_BACK) {
16105  struct nk_window *end;
16106  end = ctx->end;
16107  end->flags |= NK_WINDOW_ROM;
16108  end->next = win;
16109  win->prev = ctx->end;
16110  win->next = 0;
16111  ctx->end = win;
16112  ctx->active = ctx->end;
16113  ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM;
16114  } else {
16115  /*ctx->end->flags |= NK_WINDOW_ROM;*/
16116  ctx->begin->prev = win;
16117  win->next = ctx->begin;
16118  win->prev = 0;
16119  ctx->begin = win;
16120  ctx->begin->flags &= ~(nk_flags)NK_WINDOW_ROM;
16121  }
16122  ctx->count++;
16123 }
16124 NK_LIB void
16125 nk_remove_window(struct nk_context *ctx, struct nk_window *win)
16126 {
16127  if (win == ctx->begin || win == ctx->end) {
16128  if (win == ctx->begin) {
16129  ctx->begin = win->next;
16130  if (win->next)
16131  win->next->prev = 0;
16132  }
16133  if (win == ctx->end) {
16134  ctx->end = win->prev;
16135  if (win->prev)
16136  win->prev->next = 0;
16137  }
16138  } else {
16139  if (win->next)
16140  win->next->prev = win->prev;
16141  if (win->prev)
16142  win->prev->next = win->next;
16143  }
16144  if (win == ctx->active || !ctx->active) {
16145  ctx->active = ctx->end;
16146  if (ctx->end)
16147  ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM;
16148  }
16149  win->next = 0;
16150  win->prev = 0;
16151  ctx->count--;
16152 }
16153 NK_API int
16154 nk_begin(struct nk_context *ctx, const char *title,
16155  struct nk_rect bounds, nk_flags flags)
16156 {
16157  return nk_begin_titled(ctx, title, title, bounds, flags);
16158 }
16159 NK_API int
16160 nk_begin_titled(struct nk_context *ctx, const char *name, const char *title,
16161  struct nk_rect bounds, nk_flags flags)
16162 {
16163  struct nk_window *win;
16164  struct nk_style *style;
16165  nk_hash title_hash;
16166  int title_len;
16167  int ret = 0;
16168 
16169  NK_ASSERT(ctx);
16170  NK_ASSERT(name);
16171  NK_ASSERT(title);
16172  NK_ASSERT(ctx->style.font && ctx->style.font->width && "if this triggers you forgot to add a font");
16173  NK_ASSERT(!ctx->current && "if this triggers you missed a `nk_end` call");
16174  if (!ctx || ctx->current || !title || !name)
16175  return 0;
16176 
16177  /* find or create window */
16178  style = &ctx->style;
16179  title_len = (int)nk_strlen(name);
16180  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
16181  win = nk_find_window(ctx, title_hash, name);
16182  if (!win) {
16183  /* create new window */
16184  nk_size name_length = (nk_size)nk_strlen(name);
16185  win = (struct nk_window*)nk_create_window(ctx);
16186  NK_ASSERT(win);
16187  if (!win) return 0;
16188 
16190  nk_insert_window(ctx, win, NK_INSERT_FRONT);
16191  else nk_insert_window(ctx, win, NK_INSERT_BACK);
16192  nk_command_buffer_init(&win->buffer, &ctx->memory, NK_CLIPPING_ON);
16193 
16194  win->flags = flags;
16195  win->bounds = bounds;
16196  win->name = title_hash;
16197  name_length = NK_MIN(name_length, NK_WINDOW_MAX_NAME-1);
16198  NK_MEMCPY(win->name_string, name, name_length);
16199  win->name_string[name_length] = 0;
16200  win->popup.win = 0;
16201  if (!ctx->active)
16202  ctx->active = win;
16203  } else {
16204  /* update window */
16205  win->flags &= ~(nk_flags)(NK_WINDOW_PRIVATE-1);
16206  win->flags |= flags;
16207  if (!(win->flags & (NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE)))
16208  win->bounds = bounds;
16209  /* If this assert triggers you either:
16210  *
16211  * I.) Have more than one window with the same name or
16212  * II.) You forgot to actually draw the window.
16213  * More specific you did not call `nk_clear` (nk_clear will be
16214  * automatically called for you if you are using one of the
16215  * provided demo backends). */
16216  NK_ASSERT(win->seq != ctx->seq);
16217  win->seq = ctx->seq;
16218  if (!ctx->active && !(win->flags & NK_WINDOW_HIDDEN)) {
16219  ctx->active = win;
16220  ctx->end = win;
16221  }
16222  }
16223  if (win->flags & NK_WINDOW_HIDDEN) {
16224  ctx->current = win;
16225  win->layout = 0;
16226  return 0;
16227  } else nk_start(ctx, win);
16228 
16229  /* window overlapping */
16230  if (!(win->flags & NK_WINDOW_HIDDEN) && !(win->flags & NK_WINDOW_NO_INPUT))
16231  {
16232  int inpanel, ishovered;
16233  struct nk_window *iter = win;
16234  float h = ctx->style.font->height + 2.0f * style->window.header.padding.y +
16235  (2.0f * style->window.header.label_padding.y);
16236  struct nk_rect win_bounds = (!(win->flags & NK_WINDOW_MINIMIZED))?
16237  win->bounds: nk_rect(win->bounds.x, win->bounds.y, win->bounds.w, h);
16238 
16239  /* activate window if hovered and no other window is overlapping this window */
16240  inpanel = nk_input_has_mouse_click_down_in_rect(&ctx->input, NK_BUTTON_LEFT, win_bounds, nk_true);
16241  inpanel = inpanel && ctx->input.mouse.buttons[NK_BUTTON_LEFT].clicked;
16242  ishovered = nk_input_is_mouse_hovering_rect(&ctx->input, win_bounds);
16243  if ((win != ctx->active) && ishovered && !ctx->input.mouse.buttons[NK_BUTTON_LEFT].down) {
16244  iter = win->next;
16245  while (iter) {
16246  struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))?
16247  iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h);
16248  if (NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
16249  iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) &&
16250  (!(iter->flags & NK_WINDOW_HIDDEN)))
16251  break;
16252 
16253  if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) &&
16254  NK_INTERSECT(win->bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
16255  iter->popup.win->bounds.x, iter->popup.win->bounds.y,
16256  iter->popup.win->bounds.w, iter->popup.win->bounds.h))
16257  break;
16258  iter = iter->next;
16259  }
16260  }
16261 
16262  /* activate window if clicked */
16263  if (iter && inpanel && (win != ctx->end)) {
16264  iter = win->next;
16265  while (iter) {
16266  /* try to find a panel with higher priority in the same position */
16267  struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))?
16268  iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h);
16269  if (NK_INBOX(ctx->input.mouse.pos.x, ctx->input.mouse.pos.y,
16270  iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) &&
16271  !(iter->flags & NK_WINDOW_HIDDEN))
16272  break;
16273  if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) &&
16274  NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
16275  iter->popup.win->bounds.x, iter->popup.win->bounds.y,
16276  iter->popup.win->bounds.w, iter->popup.win->bounds.h))
16277  break;
16278  iter = iter->next;
16279  }
16280  }
16281  if (iter && !(win->flags & NK_WINDOW_ROM) && (win->flags & NK_WINDOW_BACKGROUND)) {
16282  win->flags |= (nk_flags)NK_WINDOW_ROM;
16283  iter->flags &= ~(nk_flags)NK_WINDOW_ROM;
16284  ctx->active = iter;
16285  if (!(iter->flags & NK_WINDOW_BACKGROUND)) {
16286  /* current window is active in that position so transfer to top
16287  * at the highest priority in stack */
16288  nk_remove_window(ctx, iter);
16289  nk_insert_window(ctx, iter, NK_INSERT_BACK);
16290  }
16291  } else {
16292  if (!iter && ctx->end != win) {
16293  if (!(win->flags & NK_WINDOW_BACKGROUND)) {
16294  /* current window is active in that position so transfer to top
16295  * at the highest priority in stack */
16296  nk_remove_window(ctx, win);
16297  nk_insert_window(ctx, win, NK_INSERT_BACK);
16298  }
16299  win->flags &= ~(nk_flags)NK_WINDOW_ROM;
16300  ctx->active = win;
16301  }
16302  if (ctx->end != win && !(win->flags & NK_WINDOW_BACKGROUND))
16303  win->flags |= NK_WINDOW_ROM;
16304  }
16305  }
16306  win->layout = (struct nk_panel*)nk_create_panel(ctx);
16307  ctx->current = win;
16308  ret = nk_panel_begin(ctx, title, NK_PANEL_WINDOW);
16309  win->layout->offset_x = &win->scrollbar.x;
16310  win->layout->offset_y = &win->scrollbar.y;
16311  return ret;
16312 }
16313 NK_API void
16314 nk_end(struct nk_context *ctx)
16315 {
16316  struct nk_panel *layout;
16317  NK_ASSERT(ctx);
16318  NK_ASSERT(ctx->current && "if this triggers you forgot to call `nk_begin`");
16319  if (!ctx || !ctx->current)
16320  return;
16321 
16322  layout = ctx->current->layout;
16323  if (!layout || (layout->type == NK_PANEL_WINDOW && (ctx->current->flags & NK_WINDOW_HIDDEN))) {
16324  ctx->current = 0;
16325  return;
16326  }
16327  nk_panel_end(ctx);
16328  nk_free_panel(ctx, ctx->current->layout);
16329  ctx->current = 0;
16330 }
16331 NK_API struct nk_rect
16332 nk_window_get_bounds(const struct nk_context *ctx)
16333 {
16334  NK_ASSERT(ctx);
16335  NK_ASSERT(ctx->current);
16336  if (!ctx || !ctx->current) return nk_rect(0,0,0,0);
16337  return ctx->current->bounds;
16338 }
16339 NK_API struct nk_vec2
16340 nk_window_get_position(const struct nk_context *ctx)
16341 {
16342  NK_ASSERT(ctx);
16343  NK_ASSERT(ctx->current);
16344  if (!ctx || !ctx->current) return nk_vec2(0,0);
16345  return nk_vec2(ctx->current->bounds.x, ctx->current->bounds.y);
16346 }
16347 NK_API struct nk_vec2
16348 nk_window_get_size(const struct nk_context *ctx)
16349 {
16350  NK_ASSERT(ctx);
16351  NK_ASSERT(ctx->current);
16352  if (!ctx || !ctx->current) return nk_vec2(0,0);
16353  return nk_vec2(ctx->current->bounds.w, ctx->current->bounds.h);
16354 }
16355 NK_API float
16356 nk_window_get_width(const struct nk_context *ctx)
16357 {
16358  NK_ASSERT(ctx);
16359  NK_ASSERT(ctx->current);
16360  if (!ctx || !ctx->current) return 0;
16361  return ctx->current->bounds.w;
16362 }
16363 NK_API float
16364 nk_window_get_height(const struct nk_context *ctx)
16365 {
16366  NK_ASSERT(ctx);
16367  NK_ASSERT(ctx->current);
16368  if (!ctx || !ctx->current) return 0;
16369  return ctx->current->bounds.h;
16370 }
16371 NK_API struct nk_rect
16373 {
16374  NK_ASSERT(ctx);
16375  NK_ASSERT(ctx->current);
16376  if (!ctx || !ctx->current) return nk_rect(0,0,0,0);
16377  return ctx->current->layout->clip;
16378 }
16379 NK_API struct nk_vec2
16381 {
16382  NK_ASSERT(ctx);
16383  NK_ASSERT(ctx->current);
16384  NK_ASSERT(ctx->current->layout);
16385  if (!ctx || !ctx->current) return nk_vec2(0,0);
16386  return nk_vec2(ctx->current->layout->clip.x, ctx->current->layout->clip.y);
16387 }
16388 NK_API struct nk_vec2
16390 {
16391  NK_ASSERT(ctx);
16392  NK_ASSERT(ctx->current);
16393  NK_ASSERT(ctx->current->layout);
16394  if (!ctx || !ctx->current) return nk_vec2(0,0);
16395  return nk_vec2(ctx->current->layout->clip.x + ctx->current->layout->clip.w,
16396  ctx->current->layout->clip.y + ctx->current->layout->clip.h);
16397 }
16398 NK_API struct nk_vec2
16400 {
16401  NK_ASSERT(ctx);
16402  NK_ASSERT(ctx->current);
16403  NK_ASSERT(ctx->current->layout);
16404  if (!ctx || !ctx->current) return nk_vec2(0,0);
16405  return nk_vec2(ctx->current->layout->clip.w, ctx->current->layout->clip.h);
16406 }
16407 NK_API struct nk_command_buffer*
16408 nk_window_get_canvas(struct nk_context *ctx)
16409 {
16410  NK_ASSERT(ctx);
16411  NK_ASSERT(ctx->current);
16412  NK_ASSERT(ctx->current->layout);
16413  if (!ctx || !ctx->current) return 0;
16414  return &ctx->current->buffer;
16415 }
16416 NK_API struct nk_panel*
16417 nk_window_get_panel(struct nk_context *ctx)
16418 {
16419  NK_ASSERT(ctx);
16420  NK_ASSERT(ctx->current);
16421  if (!ctx || !ctx->current) return 0;
16422  return ctx->current->layout;
16423 }
16424 NK_API int
16425 nk_window_has_focus(const struct nk_context *ctx)
16426 {
16427  NK_ASSERT(ctx);
16428  NK_ASSERT(ctx->current);
16429  NK_ASSERT(ctx->current->layout);
16430  if (!ctx || !ctx->current) return 0;
16431  return ctx->current == ctx->active;
16432 }
16433 NK_API int
16434 nk_window_is_hovered(struct nk_context *ctx)
16435 {
16436  NK_ASSERT(ctx);
16437  NK_ASSERT(ctx->current);
16438  if (!ctx || !ctx->current) return 0;
16439  if(ctx->current->flags & NK_WINDOW_HIDDEN)
16440  return 0;
16441  return nk_input_is_mouse_hovering_rect(&ctx->input, ctx->current->bounds);
16442 }
16443 NK_API int
16445 {
16446  struct nk_window *iter;
16447  NK_ASSERT(ctx);
16448  if (!ctx) return 0;
16449  iter = ctx->begin;
16450  while (iter) {
16451  /* check if window is being hovered */
16452  if(!(iter->flags & NK_WINDOW_HIDDEN)) {
16453  /* check if window popup is being hovered */
16454  if (iter->popup.active && iter->popup.win && nk_input_is_mouse_hovering_rect(&ctx->input, iter->popup.win->bounds))
16455  return 1;
16456 
16457  if (iter->flags & NK_WINDOW_MINIMIZED) {
16458  struct nk_rect header = iter->bounds;
16459  header.h = ctx->style.font->height + 2 * ctx->style.window.header.padding.y;
16460  if (nk_input_is_mouse_hovering_rect(&ctx->input, header))
16461  return 1;
16462  } else if (nk_input_is_mouse_hovering_rect(&ctx->input, iter->bounds)) {
16463  return 1;
16464  }
16465  }
16466  iter = iter->next;
16467  }
16468  return 0;
16469 }
16470 NK_API int
16471 nk_item_is_any_active(struct nk_context *ctx)
16472 {
16473  int any_hovered = nk_window_is_any_hovered(ctx);
16474  int any_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED);
16475  return any_hovered || any_active;
16476 }
16477 NK_API int
16478 nk_window_is_collapsed(struct nk_context *ctx, const char *name)
16479 {
16480  int title_len;
16481  nk_hash title_hash;
16482  struct nk_window *win;
16483  NK_ASSERT(ctx);
16484  if (!ctx) return 0;
16485 
16486  title_len = (int)nk_strlen(name);
16487  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
16488  win = nk_find_window(ctx, title_hash, name);
16489  if (!win) return 0;
16490  return win->flags & NK_WINDOW_MINIMIZED;
16491 }
16492 NK_API int
16493 nk_window_is_closed(struct nk_context *ctx, const char *name)
16494 {
16495  int title_len;
16496  nk_hash title_hash;
16497  struct nk_window *win;
16498  NK_ASSERT(ctx);
16499  if (!ctx) return 1;
16500 
16501  title_len = (int)nk_strlen(name);
16502  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
16503  win = nk_find_window(ctx, title_hash, name);
16504  if (!win) return 1;
16505  return (win->flags & NK_WINDOW_CLOSED);
16506 }
16507 NK_API int
16508 nk_window_is_hidden(struct nk_context *ctx, const char *name)
16509 {
16510  int title_len;
16511  nk_hash title_hash;
16512  struct nk_window *win;
16513  NK_ASSERT(ctx);
16514  if (!ctx) return 1;
16515 
16516  title_len = (int)nk_strlen(name);
16517  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
16518  win = nk_find_window(ctx, title_hash, name);
16519  if (!win) return 1;
16520  return (win->flags & NK_WINDOW_HIDDEN);
16521 }
16522 NK_API int
16523 nk_window_is_active(struct nk_context *ctx, const char *name)
16524 {
16525  int title_len;
16526  nk_hash title_hash;
16527  struct nk_window *win;
16528  NK_ASSERT(ctx);
16529  if (!ctx) return 0;
16530 
16531  title_len = (int)nk_strlen(name);
16532  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
16533  win = nk_find_window(ctx, title_hash, name);
16534  if (!win) return 0;
16535  return win == ctx->active;
16536 }
16537 NK_API struct nk_window*
16538 nk_window_find(struct nk_context *ctx, const char *name)
16539 {
16540  int title_len;
16541  nk_hash title_hash;
16542  title_len = (int)nk_strlen(name);
16543  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
16544  return nk_find_window(ctx, title_hash, name);
16545 }
16546 NK_API void
16547 nk_window_close(struct nk_context *ctx, const char *name)
16548 {
16549  struct nk_window *win;
16550  NK_ASSERT(ctx);
16551  if (!ctx) return;
16552  win = nk_window_find(ctx, name);
16553  if (!win) return;
16554  NK_ASSERT(ctx->current != win && "You cannot close a currently active window");
16555  if (ctx->current == win) return;
16556  win->flags |= NK_WINDOW_HIDDEN;
16557  win->flags |= NK_WINDOW_CLOSED;
16558 }
16559 NK_API void
16560 nk_window_set_bounds(struct nk_context *ctx,
16561  const char *name, struct nk_rect bounds)
16562 {
16563  struct nk_window *win;
16564  NK_ASSERT(ctx);
16565  if (!ctx) return;
16566  win = nk_window_find(ctx, name);
16567  if (!win) return;
16568  NK_ASSERT(ctx->current != win && "You cannot update a currently in procecss window");
16569  win->bounds = bounds;
16570 }
16571 NK_API void
16573  const char *name, struct nk_vec2 pos)
16574 {
16575  struct nk_window *win = nk_window_find(ctx, name);
16576  if (!win) return;
16577  win->bounds.x = pos.x;
16578  win->bounds.y = pos.y;
16579 }
16580 NK_API void
16581 nk_window_set_size(struct nk_context *ctx,
16582  const char *name, struct nk_vec2 size)
16583 {
16584  struct nk_window *win = nk_window_find(ctx, name);
16585  if (!win) return;
16586  win->bounds.w = size.x;
16587  win->bounds.h = size.y;
16588 }
16589 NK_API void
16590 nk_window_collapse(struct nk_context *ctx, const char *name,
16591  enum nk_collapse_states c)
16592 {
16593  int title_len;
16594  nk_hash title_hash;
16595  struct nk_window *win;
16596  NK_ASSERT(ctx);
16597  if (!ctx) return;
16598 
16599  title_len = (int)nk_strlen(name);
16600  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
16601  win = nk_find_window(ctx, title_hash, name);
16602  if (!win) return;
16603  if (c == NK_MINIMIZED)
16604  win->flags |= NK_WINDOW_MINIMIZED;
16605  else win->flags &= ~(nk_flags)NK_WINDOW_MINIMIZED;
16606 }
16607 NK_API void
16608 nk_window_collapse_if(struct nk_context *ctx, const char *name,
16609  enum nk_collapse_states c, int cond)
16610 {
16611  NK_ASSERT(ctx);
16612  if (!ctx || !cond) return;
16613  nk_window_collapse(ctx, name, c);
16614 }
16615 NK_API void
16616 nk_window_show(struct nk_context *ctx, const char *name, enum nk_show_states s)
16617 {
16618  int title_len;
16619  nk_hash title_hash;
16620  struct nk_window *win;
16621  NK_ASSERT(ctx);
16622  if (!ctx) return;
16623 
16624  title_len = (int)nk_strlen(name);
16625  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
16626  win = nk_find_window(ctx, title_hash, name);
16627  if (!win) return;
16628  if (s == NK_HIDDEN) {
16629  win->flags |= NK_WINDOW_HIDDEN;
16630  } else win->flags &= ~(nk_flags)NK_WINDOW_HIDDEN;
16631 }
16632 NK_API void
16633 nk_window_show_if(struct nk_context *ctx, const char *name,
16634  enum nk_show_states s, int cond)
16635 {
16636  NK_ASSERT(ctx);
16637  if (!ctx || !cond) return;
16638  nk_window_show(ctx, name, s);
16639 }
16640 
16641 NK_API void
16642 nk_window_set_focus(struct nk_context *ctx, const char *name)
16643 {
16644  int title_len;
16645  nk_hash title_hash;
16646  struct nk_window *win;
16647  NK_ASSERT(ctx);
16648  if (!ctx) return;
16649 
16650  title_len = (int)nk_strlen(name);
16651  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
16652  win = nk_find_window(ctx, title_hash, name);
16653  if (win && ctx->end != win) {
16654  nk_remove_window(ctx, win);
16655  nk_insert_window(ctx, win, NK_INSERT_BACK);
16656  }
16657  ctx->active = win;
16658 }
16659 
16660 
16661 
16662 
16663 
16664 /* ===============================================================
16665  *
16666  * POPUP
16667  *
16668  * ===============================================================*/
16669 NK_API int
16670 nk_popup_begin(struct nk_context *ctx, enum nk_popup_type type,
16671  const char *title, nk_flags flags, struct nk_rect rect)
16672 {
16673  struct nk_window *popup;
16674  struct nk_window *win;
16675  struct nk_panel *panel;
16676 
16677  int title_len;
16678  nk_hash title_hash;
16679  nk_size allocated;
16680 
16681  NK_ASSERT(ctx);
16682  NK_ASSERT(title);
16683  NK_ASSERT(ctx->current);
16684  NK_ASSERT(ctx->current->layout);
16685  if (!ctx || !ctx->current || !ctx->current->layout)
16686  return 0;
16687 
16688  win = ctx->current;
16689  panel = win->layout;
16690  NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP) && "popups are not allowed to have popups");
16691  (void)panel;
16692  title_len = (int)nk_strlen(title);
16693  title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_POPUP);
16694 
16695  popup = win->popup.win;
16696  if (!popup) {
16697  popup = (struct nk_window*)nk_create_window(ctx);
16698  popup->parent = win;
16699  win->popup.win = popup;
16700  win->popup.active = 0;
16701  win->popup.type = NK_PANEL_POPUP;
16702  }
16703 
16704  /* make sure we have correct popup */
16705  if (win->popup.name != title_hash) {
16706  if (!win->popup.active) {
16707  nk_zero(popup, sizeof(*popup));
16708  win->popup.name = title_hash;
16709  win->popup.active = 1;
16710  win->popup.type = NK_PANEL_POPUP;
16711  } else return 0;
16712  }
16713 
16714  /* popup position is local to window */
16715  ctx->current = popup;
16716  rect.x += win->layout->clip.x;
16717  rect.y += win->layout->clip.y;
16718 
16719  /* setup popup data */
16720  popup->parent = win;
16721  popup->bounds = rect;
16722  popup->seq = ctx->seq;
16723  popup->layout = (struct nk_panel*)nk_create_panel(ctx);
16724  popup->flags = flags;
16725  popup->flags |= NK_WINDOW_BORDER;
16726  if (type == NK_POPUP_DYNAMIC)
16727  popup->flags |= NK_WINDOW_DYNAMIC;
16728 
16729  popup->buffer = win->buffer;
16730  nk_start_popup(ctx, win);
16731  allocated = ctx->memory.allocated;
16732  nk_push_scissor(&popup->buffer, nk_null_rect);
16733 
16734  if (nk_panel_begin(ctx, title, NK_PANEL_POPUP)) {
16735  /* popup is running therefore invalidate parent panels */
16736  struct nk_panel *root;
16737  root = win->layout;
16738  while (root) {
16739  root->flags |= NK_WINDOW_ROM;
16740  root->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM;
16741  root = root->parent;
16742  }
16743  win->popup.active = 1;
16744  popup->layout->offset_x = &popup->scrollbar.x;
16745  popup->layout->offset_y = &popup->scrollbar.y;
16746  popup->layout->parent = win->layout;
16747  return 1;
16748  } else {
16749  /* popup was closed/is invalid so cleanup */
16750  struct nk_panel *root;
16751  root = win->layout;
16752  while (root) {
16753  root->flags |= NK_WINDOW_REMOVE_ROM;
16754  root = root->parent;
16755  }
16756  win->popup.buf.active = 0;
16757  win->popup.active = 0;
16758  ctx->memory.allocated = allocated;
16759  ctx->current = win;
16760  nk_free_panel(ctx, popup->layout);
16761  popup->layout = 0;
16762  return 0;
16763  }
16764 }
16765 NK_LIB int
16766 nk_nonblock_begin(struct nk_context *ctx,
16767  nk_flags flags, struct nk_rect body, struct nk_rect header,
16768  enum nk_panel_type panel_type)
16769 {
16770  struct nk_window *popup;
16771  struct nk_window *win;
16772  struct nk_panel *panel;
16773  int is_active = nk_true;
16774 
16775  NK_ASSERT(ctx);
16776  NK_ASSERT(ctx->current);
16777  NK_ASSERT(ctx->current->layout);
16778  if (!ctx || !ctx->current || !ctx->current->layout)
16779  return 0;
16780 
16781  /* popups cannot have popups */
16782  win = ctx->current;
16783  panel = win->layout;
16784  NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP));
16785  (void)panel;
16786  popup = win->popup.win;
16787  if (!popup) {
16788  /* create window for nonblocking popup */
16789  popup = (struct nk_window*)nk_create_window(ctx);
16790  popup->parent = win;
16791  win->popup.win = popup;
16792  win->popup.type = panel_type;
16793  nk_command_buffer_init(&popup->buffer, &ctx->memory, NK_CLIPPING_ON);
16794  } else {
16795  /* close the popup if user pressed outside or in the header */
16796  int pressed, in_body, in_header;
16798  in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body);
16799  in_header = nk_input_is_mouse_hovering_rect(&ctx->input, header);
16800  if (pressed && (!in_body || in_header))
16801  is_active = nk_false;
16802  }
16803  win->popup.header = header;
16804 
16805  if (!is_active) {
16806  /* remove read only mode from all parent panels */
16807  struct nk_panel *root = win->layout;
16808  while (root) {
16809  root->flags |= NK_WINDOW_REMOVE_ROM;
16810  root = root->parent;
16811  }
16812  return is_active;
16813  }
16814  popup->bounds = body;
16815  popup->parent = win;
16816  popup->layout = (struct nk_panel*)nk_create_panel(ctx);
16817  popup->flags = flags;
16818  popup->flags |= NK_WINDOW_BORDER;
16819  popup->flags |= NK_WINDOW_DYNAMIC;
16820  popup->seq = ctx->seq;
16821  win->popup.active = 1;
16822  NK_ASSERT(popup->layout);
16823 
16824  nk_start_popup(ctx, win);
16825  popup->buffer = win->buffer;
16826  nk_push_scissor(&popup->buffer, nk_null_rect);
16827  ctx->current = popup;
16828 
16829  nk_panel_begin(ctx, 0, panel_type);
16830  win->buffer = popup->buffer;
16831  popup->layout->parent = win->layout;
16832  popup->layout->offset_x = &popup->scrollbar.x;
16833  popup->layout->offset_y = &popup->scrollbar.y;
16834 
16835  /* set read only mode to all parent panels */
16836  {struct nk_panel *root;
16837  root = win->layout;
16838  while (root) {
16839  root->flags |= NK_WINDOW_ROM;
16840  root = root->parent;
16841  }}
16842  return is_active;
16843 }
16844 NK_API void
16845 nk_popup_close(struct nk_context *ctx)
16846 {
16847  struct nk_window *popup;
16848  NK_ASSERT(ctx);
16849  if (!ctx || !ctx->current) return;
16850 
16851  popup = ctx->current;
16852  NK_ASSERT(popup->parent);
16853  NK_ASSERT(popup->layout->type & NK_PANEL_SET_POPUP);
16854  popup->flags |= NK_WINDOW_HIDDEN;
16855 }
16856 NK_API void
16857 nk_popup_end(struct nk_context *ctx)
16858 {
16859  struct nk_window *win;
16860  struct nk_window *popup;
16861 
16862  NK_ASSERT(ctx);
16863  NK_ASSERT(ctx->current);
16864  NK_ASSERT(ctx->current->layout);
16865  if (!ctx || !ctx->current || !ctx->current->layout)
16866  return;
16867 
16868  popup = ctx->current;
16869  if (!popup->parent) return;
16870  win = popup->parent;
16871  if (popup->flags & NK_WINDOW_HIDDEN) {
16872  struct nk_panel *root;
16873  root = win->layout;
16874  while (root) {
16875  root->flags |= NK_WINDOW_REMOVE_ROM;
16876  root = root->parent;
16877  }
16878  win->popup.active = 0;
16879  }
16880  nk_push_scissor(&popup->buffer, nk_null_rect);
16881  nk_end(ctx);
16882 
16883  win->buffer = popup->buffer;
16884  nk_finish_popup(ctx, win);
16885  ctx->current = win;
16886  nk_push_scissor(&win->buffer, win->layout->clip);
16887 }
16888 
16889 
16890 
16891 
16892 
16893 /* ==============================================================
16894  *
16895  * CONTEXTUAL
16896  *
16897  * ===============================================================*/
16898 NK_API int
16899 nk_contextual_begin(struct nk_context *ctx, nk_flags flags, struct nk_vec2 size,
16900  struct nk_rect trigger_bounds)
16901 {
16902  struct nk_window *win;
16903  struct nk_window *popup;
16904  struct nk_rect body;
16905 
16906  NK_STORAGE const struct nk_rect null_rect = {-1,-1,0,0};
16907  int is_clicked = 0;
16908  int is_open = 0;
16909  int ret = 0;
16910 
16911  NK_ASSERT(ctx);
16912  NK_ASSERT(ctx->current);
16913  NK_ASSERT(ctx->current->layout);
16914  if (!ctx || !ctx->current || !ctx->current->layout)
16915  return 0;
16916 
16917  win = ctx->current;
16918  ++win->popup.con_count;
16919  if (ctx->current != ctx->active)
16920  return 0;
16921 
16922  /* check if currently active contextual is active */
16923  popup = win->popup.win;
16924  is_open = (popup && win->popup.type == NK_PANEL_CONTEXTUAL);
16925  is_clicked = nk_input_mouse_clicked(&ctx->input, NK_BUTTON_RIGHT, trigger_bounds);
16926  if (win->popup.active_con && win->popup.con_count != win->popup.active_con)
16927  return 0;
16928  if (!is_open && win->popup.active_con)
16929  win->popup.active_con = 0;
16930  if ((!is_open && !is_clicked))
16931  return 0;
16932 
16933  /* calculate contextual position on click */
16934  win->popup.active_con = win->popup.con_count;
16935  if (is_clicked) {
16936  body.x = ctx->input.mouse.pos.x;
16937  body.y = ctx->input.mouse.pos.y;
16938  } else {
16939  body.x = popup->bounds.x;
16940  body.y = popup->bounds.y;
16941  }
16942  body.w = size.x;
16943  body.h = size.y;
16944 
16945  /* start nonblocking contextual popup */
16946  ret = nk_nonblock_begin(ctx, flags|NK_WINDOW_NO_SCROLLBAR, body,
16947  null_rect, NK_PANEL_CONTEXTUAL);
16948  if (ret) win->popup.type = NK_PANEL_CONTEXTUAL;
16949  else {
16950  win->popup.active_con = 0;
16951  win->popup.type = NK_PANEL_NONE;
16952  if (win->popup.win)
16953  win->popup.win->flags = 0;
16954  }
16955  return ret;
16956 }
16957 NK_API int
16958 nk_contextual_item_text(struct nk_context *ctx, const char *text, int len,
16959  nk_flags alignment)
16960 {
16961  struct nk_window *win;
16962  const struct nk_input *in;
16963  const struct nk_style *style;
16964 
16965  struct nk_rect bounds;
16966  enum nk_widget_layout_states state;
16967 
16968  NK_ASSERT(ctx);
16969  NK_ASSERT(ctx->current);
16970  NK_ASSERT(ctx->current->layout);
16971  if (!ctx || !ctx->current || !ctx->current->layout)
16972  return 0;
16973 
16974  win = ctx->current;
16975  style = &ctx->style;
16976  state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
16977  if (!state) return nk_false;
16978 
16979  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
16980  if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds,
16981  text, len, alignment, NK_BUTTON_DEFAULT, &style->contextual_button, in, style->font)) {
16982  nk_contextual_close(ctx);
16983  return nk_true;
16984  }
16985  return nk_false;
16986 }
16987 NK_API int
16988 nk_contextual_item_label(struct nk_context *ctx, const char *label, nk_flags align)
16989 {
16990  return nk_contextual_item_text(ctx, label, nk_strlen(label), align);
16991 }
16992 NK_API int
16993 nk_contextual_item_image_text(struct nk_context *ctx, struct nk_image img,
16994  const char *text, int len, nk_flags align)
16995 {
16996  struct nk_window *win;
16997  const struct nk_input *in;
16998  const struct nk_style *style;
16999 
17000  struct nk_rect bounds;
17001  enum nk_widget_layout_states state;
17002 
17003  NK_ASSERT(ctx);
17004  NK_ASSERT(ctx->current);
17005  NK_ASSERT(ctx->current->layout);
17006  if (!ctx || !ctx->current || !ctx->current->layout)
17007  return 0;
17008 
17009  win = ctx->current;
17010  style = &ctx->style;
17011  state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
17012  if (!state) return nk_false;
17013 
17014  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
17015  if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, bounds,
17016  img, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)){
17017  nk_contextual_close(ctx);
17018  return nk_true;
17019  }
17020  return nk_false;
17021 }
17022 NK_API int
17023 nk_contextual_item_image_label(struct nk_context *ctx, struct nk_image img,
17024  const char *label, nk_flags align)
17025 {
17026  return nk_contextual_item_image_text(ctx, img, label, nk_strlen(label), align);
17027 }
17028 NK_API int
17030  const char *text, int len, nk_flags align)
17031 {
17032  struct nk_window *win;
17033  const struct nk_input *in;
17034  const struct nk_style *style;
17035 
17036  struct nk_rect bounds;
17037  enum nk_widget_layout_states state;
17038 
17039  NK_ASSERT(ctx);
17040  NK_ASSERT(ctx->current);
17041  NK_ASSERT(ctx->current->layout);
17042  if (!ctx || !ctx->current || !ctx->current->layout)
17043  return 0;
17044 
17045  win = ctx->current;
17046  style = &ctx->style;
17047  state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
17048  if (!state) return nk_false;
17049 
17050  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
17051  if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds,
17052  symbol, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)) {
17053  nk_contextual_close(ctx);
17054  return nk_true;
17055  }
17056  return nk_false;
17057 }
17058 NK_API int
17060  const char *text, nk_flags align)
17061 {
17062  return nk_contextual_item_symbol_text(ctx, symbol, text, nk_strlen(text), align);
17063 }
17064 NK_API void
17065 nk_contextual_close(struct nk_context *ctx)
17066 {
17067  NK_ASSERT(ctx);
17068  NK_ASSERT(ctx->current);
17069  NK_ASSERT(ctx->current->layout);
17070  if (!ctx || !ctx->current || !ctx->current->layout) return;
17071  nk_popup_close(ctx);
17072 }
17073 NK_API void
17074 nk_contextual_end(struct nk_context *ctx)
17075 {
17076  struct nk_window *popup;
17077  struct nk_panel *panel;
17078  NK_ASSERT(ctx);
17079  NK_ASSERT(ctx->current);
17080  if (!ctx || !ctx->current) return;
17081 
17082  popup = ctx->current;
17083  panel = popup->layout;
17084  NK_ASSERT(popup->parent);
17085  NK_ASSERT(panel->type & NK_PANEL_SET_POPUP);
17086  if (panel->flags & NK_WINDOW_DYNAMIC) {
17087  /* Close behavior
17088  This is a bit of a hack solution since we do not know before we end our popup
17089  how big it will be. We therefore do not directly know when a
17090  click outside the non-blocking popup must close it at that direct frame.
17091  Instead it will be closed in the next frame.*/
17092  struct nk_rect body = {0,0,0,0};
17093  if (panel->at_y < (panel->bounds.y + panel->bounds.h)) {
17094  struct nk_vec2 padding = nk_panel_get_padding(&ctx->style, panel->type);
17095  body = panel->bounds;
17096  body.y = (panel->at_y + panel->footer_height + panel->border + padding.y + panel->row.height);
17097  body.h = (panel->bounds.y + panel->bounds.h) - body.y;
17098  }
17099  {int pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT);
17100  int in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body);
17101  if (pressed && in_body)
17102  popup->flags |= NK_WINDOW_HIDDEN;
17103  }
17104  }
17105  if (popup->flags & NK_WINDOW_HIDDEN)
17106  popup->seq = 0;
17107  nk_popup_end(ctx);
17108  return;
17109 }
17110 
17111 
17112 
17113 
17114 
17115 /* ===============================================================
17116  *
17117  * MENU
17118  *
17119  * ===============================================================*/
17120 NK_API void
17121 nk_menubar_begin(struct nk_context *ctx)
17122 {
17123  struct nk_panel *layout;
17124  NK_ASSERT(ctx);
17125  NK_ASSERT(ctx->current);
17126  NK_ASSERT(ctx->current->layout);
17127  if (!ctx || !ctx->current || !ctx->current->layout)
17128  return;
17129 
17130  layout = ctx->current->layout;
17131  NK_ASSERT(layout->at_y == layout->bounds.y);
17132  /* if this assert triggers you allocated space between nk_begin and nk_menubar_begin.
17133  If you want a menubar the first nuklear function after `nk_begin` has to be a
17134  `nk_menubar_begin` call. Inside the menubar you then have to allocate space for
17135  widgets (also supports multiple rows).
17136  Example:
17137  if (nk_begin(...)) {
17138  nk_menubar_begin(...);
17139  nk_layout_xxxx(...);
17140  nk_button(...);
17141  nk_layout_xxxx(...);
17142  nk_button(...);
17143  nk_menubar_end(...);
17144  }
17145  nk_end(...);
17146  */
17147  if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED)
17148  return;
17149 
17150  layout->menu.x = layout->at_x;
17151  layout->menu.y = layout->at_y + layout->row.height;
17152  layout->menu.w = layout->bounds.w;
17153  layout->menu.offset.x = *layout->offset_x;
17154  layout->menu.offset.y = *layout->offset_y;
17155  *layout->offset_y = 0;
17156 }
17157 NK_API void
17158 nk_menubar_end(struct nk_context *ctx)
17159 {
17160  struct nk_window *win;
17161  struct nk_panel *layout;
17162  struct nk_command_buffer *out;
17163 
17164  NK_ASSERT(ctx);
17165  NK_ASSERT(ctx->current);
17166  NK_ASSERT(ctx->current->layout);
17167  if (!ctx || !ctx->current || !ctx->current->layout)
17168  return;
17169 
17170  win = ctx->current;
17171  out = &win->buffer;
17172  layout = win->layout;
17173  if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED)
17174  return;
17175 
17176  layout->menu.h = layout->at_y - layout->menu.y;
17177  layout->bounds.y += layout->menu.h + ctx->style.window.spacing.y + layout->row.height;
17178  layout->bounds.h -= layout->menu.h + ctx->style.window.spacing.y + layout->row.height;
17179 
17180  *layout->offset_x = layout->menu.offset.x;
17181  *layout->offset_y = layout->menu.offset.y;
17182  layout->at_y = layout->bounds.y - layout->row.height;
17183 
17184  layout->clip.y = layout->bounds.y;
17185  layout->clip.h = layout->bounds.h;
17186  nk_push_scissor(out, layout->clip);
17187 }
17188 NK_INTERN int
17189 nk_menu_begin(struct nk_context *ctx, struct nk_window *win,
17190  const char *id, int is_clicked, struct nk_rect header, struct nk_vec2 size)
17191 {
17192  int is_open = 0;
17193  int is_active = 0;
17194  struct nk_rect body;
17195  struct nk_window *popup;
17196  nk_hash hash = nk_murmur_hash(id, (int)nk_strlen(id), NK_PANEL_MENU);
17197 
17198  NK_ASSERT(ctx);
17199  NK_ASSERT(ctx->current);
17200  NK_ASSERT(ctx->current->layout);
17201  if (!ctx || !ctx->current || !ctx->current->layout)
17202  return 0;
17203 
17204  body.x = header.x;
17205  body.w = size.x;
17206  body.y = header.y + header.h;
17207  body.h = size.y;
17208 
17209  popup = win->popup.win;
17210  is_open = popup ? nk_true : nk_false;
17211  is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_MENU);
17212  if ((is_clicked && is_open && !is_active) || (is_open && !is_active) ||
17213  (!is_open && !is_active && !is_clicked)) return 0;
17214  if (!nk_nonblock_begin(ctx, NK_WINDOW_NO_SCROLLBAR, body, header, NK_PANEL_MENU))
17215  return 0;
17216 
17217  win->popup.type = NK_PANEL_MENU;
17218  win->popup.name = hash;
17219  return 1;
17220 }
17221 NK_API int
17222 nk_menu_begin_text(struct nk_context *ctx, const char *title, int len,
17223  nk_flags align, struct nk_vec2 size)
17224 {
17225  struct nk_window *win;
17226  const struct nk_input *in;
17227  struct nk_rect header;
17228  int is_clicked = nk_false;
17229  nk_flags state;
17230 
17231  NK_ASSERT(ctx);
17232  NK_ASSERT(ctx->current);
17233  NK_ASSERT(ctx->current->layout);
17234  if (!ctx || !ctx->current || !ctx->current->layout)
17235  return 0;
17236 
17237  win = ctx->current;
17238  state = nk_widget(&header, ctx);
17239  if (!state) return 0;
17240  in = (state == NK_WIDGET_ROM || win->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
17241  if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, header,
17242  title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font))
17243  is_clicked = nk_true;
17244  return nk_menu_begin(ctx, win, title, is_clicked, header, size);
17245 }
17246 NK_API int nk_menu_begin_label(struct nk_context *ctx,
17247  const char *text, nk_flags align, struct nk_vec2 size)
17248 {
17249  return nk_menu_begin_text(ctx, text, nk_strlen(text), align, size);
17250 }
17251 NK_API int
17252 nk_menu_begin_image(struct nk_context *ctx, const char *id, struct nk_image img,
17253  struct nk_vec2 size)
17254 {
17255  struct nk_window *win;
17256  struct nk_rect header;
17257  const struct nk_input *in;
17258  int is_clicked = nk_false;
17259  nk_flags state;
17260 
17261  NK_ASSERT(ctx);
17262  NK_ASSERT(ctx->current);
17263  NK_ASSERT(ctx->current->layout);
17264  if (!ctx || !ctx->current || !ctx->current->layout)
17265  return 0;
17266 
17267  win = ctx->current;
17268  state = nk_widget(&header, ctx);
17269  if (!state) return 0;
17270  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
17271  if (nk_do_button_image(&ctx->last_widget_state, &win->buffer, header,
17272  img, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in))
17273  is_clicked = nk_true;
17274  return nk_menu_begin(ctx, win, id, is_clicked, header, size);
17275 }
17276 NK_API int
17277 nk_menu_begin_symbol(struct nk_context *ctx, const char *id,
17278  enum nk_symbol_type sym, struct nk_vec2 size)
17279 {
17280  struct nk_window *win;
17281  const struct nk_input *in;
17282  struct nk_rect header;
17283  int is_clicked = nk_false;
17284  nk_flags state;
17285 
17286  NK_ASSERT(ctx);
17287  NK_ASSERT(ctx->current);
17288  NK_ASSERT(ctx->current->layout);
17289  if (!ctx || !ctx->current || !ctx->current->layout)
17290  return 0;
17291 
17292  win = ctx->current;
17293  state = nk_widget(&header, ctx);
17294  if (!state) return 0;
17295  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
17296  if (nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, header,
17297  sym, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font))
17298  is_clicked = nk_true;
17299  return nk_menu_begin(ctx, win, id, is_clicked, header, size);
17300 }
17301 NK_API int
17302 nk_menu_begin_image_text(struct nk_context *ctx, const char *title, int len,
17303  nk_flags align, struct nk_image img, struct nk_vec2 size)
17304 {
17305  struct nk_window *win;
17306  struct nk_rect header;
17307  const struct nk_input *in;
17308  int is_clicked = nk_false;
17309  nk_flags state;
17310 
17311  NK_ASSERT(ctx);
17312  NK_ASSERT(ctx->current);
17313  NK_ASSERT(ctx->current->layout);
17314  if (!ctx || !ctx->current || !ctx->current->layout)
17315  return 0;
17316 
17317  win = ctx->current;
17318  state = nk_widget(&header, ctx);
17319  if (!state) return 0;
17320  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
17321  if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer,
17322  header, img, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button,
17323  ctx->style.font, in))
17324  is_clicked = nk_true;
17325  return nk_menu_begin(ctx, win, title, is_clicked, header, size);
17326 }
17327 NK_API int
17329  const char *title, nk_flags align, struct nk_image img, struct nk_vec2 size)
17330 {
17331  return nk_menu_begin_image_text(ctx, title, nk_strlen(title), align, img, size);
17332 }
17333 NK_API int
17334 nk_menu_begin_symbol_text(struct nk_context *ctx, const char *title, int len,
17335  nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size)
17336 {
17337  struct nk_window *win;
17338  struct nk_rect header;
17339  const struct nk_input *in;
17340  int is_clicked = nk_false;
17341  nk_flags state;
17342 
17343  NK_ASSERT(ctx);
17344  NK_ASSERT(ctx->current);
17345  NK_ASSERT(ctx->current->layout);
17346  if (!ctx || !ctx->current || !ctx->current->layout)
17347  return 0;
17348 
17349  win = ctx->current;
17350  state = nk_widget(&header, ctx);
17351  if (!state) return 0;
17352 
17353  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
17354  if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer,
17355  header, sym, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button,
17356  ctx->style.font, in)) is_clicked = nk_true;
17357  return nk_menu_begin(ctx, win, title, is_clicked, header, size);
17358 }
17359 NK_API int
17361  const char *title, nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size )
17362 {
17363  return nk_menu_begin_symbol_text(ctx, title, nk_strlen(title), align,sym,size);
17364 }
17365 NK_API int
17366 nk_menu_item_text(struct nk_context *ctx, const char *title, int len, nk_flags align)
17367 {
17368  return nk_contextual_item_text(ctx, title, len, align);
17369 }
17370 NK_API int
17371 nk_menu_item_label(struct nk_context *ctx, const char *label, nk_flags align)
17372 {
17373  return nk_contextual_item_label(ctx, label, align);
17374 }
17375 NK_API int
17376 nk_menu_item_image_label(struct nk_context *ctx, struct nk_image img,
17377  const char *label, nk_flags align)
17378 {
17379  return nk_contextual_item_image_label(ctx, img, label, align);
17380 }
17381 NK_API int
17382 nk_menu_item_image_text(struct nk_context *ctx, struct nk_image img,
17383  const char *text, int len, nk_flags align)
17384 {
17385  return nk_contextual_item_image_text(ctx, img, text, len, align);
17386 }
17387 NK_API int nk_menu_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
17388  const char *text, int len, nk_flags align)
17389 {
17390  return nk_contextual_item_symbol_text(ctx, sym, text, len, align);
17391 }
17392 NK_API int nk_menu_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym,
17393  const char *label, nk_flags align)
17394 {
17395  return nk_contextual_item_symbol_label(ctx, sym, label, align);
17396 }
17397 NK_API void nk_menu_close(struct nk_context *ctx)
17398 {
17399  nk_contextual_close(ctx);
17400 }
17401 NK_API void
17402 nk_menu_end(struct nk_context *ctx)
17403 {
17404  nk_contextual_end(ctx);
17405 }
17406 
17407 
17408 
17409 
17410 
17411 /* ===============================================================
17412  *
17413  * LAYOUT
17414  *
17415  * ===============================================================*/
17416 NK_API void
17417 nk_layout_set_min_row_height(struct nk_context *ctx, float height)
17418 {
17419  struct nk_window *win;
17420  struct nk_panel *layout;
17421 
17422  NK_ASSERT(ctx);
17423  NK_ASSERT(ctx->current);
17424  NK_ASSERT(ctx->current->layout);
17425  if (!ctx || !ctx->current || !ctx->current->layout)
17426  return;
17427 
17428  win = ctx->current;
17429  layout = win->layout;
17430  layout->row.min_height = height;
17431 }
17432 NK_API void
17434 {
17435  struct nk_window *win;
17436  struct nk_panel *layout;
17437 
17438  NK_ASSERT(ctx);
17439  NK_ASSERT(ctx->current);
17440  NK_ASSERT(ctx->current->layout);
17441  if (!ctx || !ctx->current || !ctx->current->layout)
17442  return;
17443 
17444  win = ctx->current;
17445  layout = win->layout;
17446  layout->row.min_height = ctx->style.font->height;
17447  layout->row.min_height += ctx->style.text.padding.y*2;
17448  layout->row.min_height += ctx->style.window.min_row_height_padding*2;
17449 }
17450 NK_LIB float
17451 nk_layout_row_calculate_usable_space(const struct nk_style *style, enum nk_panel_type type,
17452  float total_space, int columns)
17453 {
17454  float panel_padding;
17455  float panel_spacing;
17456  float panel_space;
17457 
17458  struct nk_vec2 spacing;
17459  struct nk_vec2 padding;
17460 
17461  spacing = style->window.spacing;
17462  padding = nk_panel_get_padding(style, type);
17463 
17464  /* calculate the usable panel space */
17465  panel_padding = 2 * padding.x;
17466  panel_spacing = (float)NK_MAX(columns - 1, 0) * spacing.x;
17467  panel_space = total_space - panel_padding - panel_spacing;
17468  return panel_space;
17469 }
17470 NK_LIB void
17471 nk_panel_layout(const struct nk_context *ctx, struct nk_window *win,
17472  float height, int cols)
17473 {
17474  struct nk_panel *layout;
17475  const struct nk_style *style;
17476  struct nk_command_buffer *out;
17477 
17478  struct nk_vec2 item_spacing;
17479  struct nk_color color;
17480 
17481  NK_ASSERT(ctx);
17482  NK_ASSERT(ctx->current);
17483  NK_ASSERT(ctx->current->layout);
17484  if (!ctx || !ctx->current || !ctx->current->layout)
17485  return;
17486 
17487  /* prefetch some configuration data */
17488  layout = win->layout;
17489  style = &ctx->style;
17490  out = &win->buffer;
17491  color = style->window.background;
17492  item_spacing = style->window.spacing;
17493 
17494  /* if one of these triggers you forgot to add an `if` condition around either
17495  a window, group, popup, combobox or contextual menu `begin` and `end` block.
17496  Example:
17497  if (nk_begin(...) {...} nk_end(...); or
17498  if (nk_group_begin(...) { nk_group_end(...);} */
17499  NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED));
17500  NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN));
17501  NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED));
17502 
17503  /* update the current row and set the current row layout */
17504  layout->row.index = 0;
17505  layout->at_y += layout->row.height;
17506  layout->row.columns = cols;
17507  if (height == 0.0f)
17508  layout->row.height = NK_MAX(height, layout->row.min_height) + item_spacing.y;
17509  else layout->row.height = height + item_spacing.y;
17510 
17511  layout->row.item_offset = 0;
17512  if (layout->flags & NK_WINDOW_DYNAMIC) {
17513  /* draw background for dynamic panels */
17514  struct nk_rect background;
17515  background.x = win->bounds.x;
17516  background.w = win->bounds.w;
17517  background.y = layout->at_y - 1.0f;
17518  background.h = layout->row.height + 1.0f;
17519  nk_fill_rect(out, background, 0, color);
17520  }
17521 }
17522 NK_LIB void
17523 nk_row_layout(struct nk_context *ctx, enum nk_layout_format fmt,
17524  float height, int cols, int width)
17525 {
17526  /* update the current row and set the current row layout */
17527  struct nk_window *win;
17528  NK_ASSERT(ctx);
17529  NK_ASSERT(ctx->current);
17530  NK_ASSERT(ctx->current->layout);
17531  if (!ctx || !ctx->current || !ctx->current->layout)
17532  return;
17533 
17534  win = ctx->current;
17535  nk_panel_layout(ctx, win, height, cols);
17536  if (fmt == NK_DYNAMIC)
17538  else win->layout->row.type = NK_LAYOUT_STATIC_FIXED;
17539 
17540  win->layout->row.ratio = 0;
17541  win->layout->row.filled = 0;
17542  win->layout->row.item_offset = 0;
17543  win->layout->row.item_width = (float)width;
17544 }
17545 NK_API float
17546 nk_layout_ratio_from_pixel(struct nk_context *ctx, float pixel_width)
17547 {
17548  struct nk_window *win;
17549  NK_ASSERT(ctx);
17550  NK_ASSERT(pixel_width);
17551  if (!ctx || !ctx->current || !ctx->current->layout) return 0;
17552  win = ctx->current;
17553  return NK_CLAMP(0.0f, pixel_width/win->bounds.x, 1.0f);
17554 }
17555 NK_API void
17556 nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols)
17557 {
17558  nk_row_layout(ctx, NK_DYNAMIC, height, cols, 0);
17559 }
17560 NK_API void
17561 nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols)
17562 {
17563  nk_row_layout(ctx, NK_STATIC, height, cols, item_width);
17564 }
17565 NK_API void
17566 nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt,
17567  float row_height, int cols)
17568 {
17569  struct nk_window *win;
17570  struct nk_panel *layout;
17571 
17572  NK_ASSERT(ctx);
17573  NK_ASSERT(ctx->current);
17574  NK_ASSERT(ctx->current->layout);
17575  if (!ctx || !ctx->current || !ctx->current->layout)
17576  return;
17577 
17578  win = ctx->current;
17579  layout = win->layout;
17580  nk_panel_layout(ctx, win, row_height, cols);
17581  if (fmt == NK_DYNAMIC)
17582  layout->row.type = NK_LAYOUT_DYNAMIC_ROW;
17583  else layout->row.type = NK_LAYOUT_STATIC_ROW;
17584 
17585  layout->row.ratio = 0;
17586  layout->row.filled = 0;
17587  layout->row.item_width = 0;
17588  layout->row.item_offset = 0;
17589  layout->row.columns = cols;
17590 }
17591 NK_API void
17592 nk_layout_row_push(struct nk_context *ctx, float ratio_or_width)
17593 {
17594  struct nk_window *win;
17595  struct nk_panel *layout;
17596 
17597  NK_ASSERT(ctx);
17598  NK_ASSERT(ctx->current);
17599  NK_ASSERT(ctx->current->layout);
17600  if (!ctx || !ctx->current || !ctx->current->layout)
17601  return;
17602 
17603  win = ctx->current;
17604  layout = win->layout;
17605  NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW);
17606  if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW)
17607  return;
17608 
17609  if (layout->row.type == NK_LAYOUT_DYNAMIC_ROW) {
17610  float ratio = ratio_or_width;
17611  if ((ratio + layout->row.filled) > 1.0f) return;
17612  if (ratio > 0.0f)
17613  layout->row.item_width = NK_SATURATE(ratio);
17614  else layout->row.item_width = 1.0f - layout->row.filled;
17615  } else layout->row.item_width = ratio_or_width;
17616 }
17617 NK_API void
17618 nk_layout_row_end(struct nk_context *ctx)
17619 {
17620  struct nk_window *win;
17621  struct nk_panel *layout;
17622 
17623  NK_ASSERT(ctx);
17624  NK_ASSERT(ctx->current);
17625  NK_ASSERT(ctx->current->layout);
17626  if (!ctx || !ctx->current || !ctx->current->layout)
17627  return;
17628 
17629  win = ctx->current;
17630  layout = win->layout;
17631  NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW);
17632  if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW)
17633  return;
17634  layout->row.item_width = 0;
17635  layout->row.item_offset = 0;
17636 }
17637 NK_API void
17638 nk_layout_row(struct nk_context *ctx, enum nk_layout_format fmt,
17639  float height, int cols, const float *ratio)
17640 {
17641  int i;
17642  int n_undef = 0;
17643  struct nk_window *win;
17644  struct nk_panel *layout;
17645 
17646  NK_ASSERT(ctx);
17647  NK_ASSERT(ctx->current);
17648  NK_ASSERT(ctx->current->layout);
17649  if (!ctx || !ctx->current || !ctx->current->layout)
17650  return;
17651 
17652  win = ctx->current;
17653  layout = win->layout;
17654  nk_panel_layout(ctx, win, height, cols);
17655  if (fmt == NK_DYNAMIC) {
17656  /* calculate width of undefined widget ratios */
17657  float r = 0;
17658  layout->row.ratio = ratio;
17659  for (i = 0; i < cols; ++i) {
17660  if (ratio[i] < 0.0f)
17661  n_undef++;
17662  else r += ratio[i];
17663  }
17664  r = NK_SATURATE(1.0f - r);
17665  layout->row.type = NK_LAYOUT_DYNAMIC;
17666  layout->row.item_width = (r > 0 && n_undef > 0) ? (r / (float)n_undef):0;
17667  } else {
17668  layout->row.ratio = ratio;
17669  layout->row.type = NK_LAYOUT_STATIC;
17670  layout->row.item_width = 0;
17671  layout->row.item_offset = 0;
17672  }
17673  layout->row.item_offset = 0;
17674  layout->row.filled = 0;
17675 }
17676 NK_API void
17677 nk_layout_row_template_begin(struct nk_context *ctx, float height)
17678 {
17679  struct nk_window *win;
17680  struct nk_panel *layout;
17681 
17682  NK_ASSERT(ctx);
17683  NK_ASSERT(ctx->current);
17684  NK_ASSERT(ctx->current->layout);
17685  if (!ctx || !ctx->current || !ctx->current->layout)
17686  return;
17687 
17688  win = ctx->current;
17689  layout = win->layout;
17690  nk_panel_layout(ctx, win, height, 1);
17691  layout->row.type = NK_LAYOUT_TEMPLATE;
17692  layout->row.columns = 0;
17693  layout->row.ratio = 0;
17694  layout->row.item_width = 0;
17695  layout->row.item_height = 0;
17696  layout->row.item_offset = 0;
17697  layout->row.filled = 0;
17698  layout->row.item.x = 0;
17699  layout->row.item.y = 0;
17700  layout->row.item.w = 0;
17701  layout->row.item.h = 0;
17702 }
17703 NK_API void
17705 {
17706  struct nk_window *win;
17707  struct nk_panel *layout;
17708 
17709  NK_ASSERT(ctx);
17710  NK_ASSERT(ctx->current);
17711  NK_ASSERT(ctx->current->layout);
17712  if (!ctx || !ctx->current || !ctx->current->layout)
17713  return;
17714 
17715  win = ctx->current;
17716  layout = win->layout;
17717  NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
17718  NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
17719  if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
17720  if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
17721  layout->row.templates[layout->row.columns++] = -1.0f;
17722 }
17723 NK_API void
17724 nk_layout_row_template_push_variable(struct nk_context *ctx, float min_width)
17725 {
17726  struct nk_window *win;
17727  struct nk_panel *layout;
17728 
17729  NK_ASSERT(ctx);
17730  NK_ASSERT(ctx->current);
17731  NK_ASSERT(ctx->current->layout);
17732  if (!ctx || !ctx->current || !ctx->current->layout)
17733  return;
17734 
17735  win = ctx->current;
17736  layout = win->layout;
17737  NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
17738  NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
17739  if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
17740  if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
17741  layout->row.templates[layout->row.columns++] = -min_width;
17742 }
17743 NK_API void
17744 nk_layout_row_template_push_static(struct nk_context *ctx, float width)
17745 {
17746  struct nk_window *win;
17747  struct nk_panel *layout;
17748 
17749  NK_ASSERT(ctx);
17750  NK_ASSERT(ctx->current);
17751  NK_ASSERT(ctx->current->layout);
17752  if (!ctx || !ctx->current || !ctx->current->layout)
17753  return;
17754 
17755  win = ctx->current;
17756  layout = win->layout;
17757  NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
17758  NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
17759  if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
17760  if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
17761  layout->row.templates[layout->row.columns++] = width;
17762 }
17763 NK_API void
17765 {
17766  struct nk_window *win;
17767  struct nk_panel *layout;
17768 
17769  int i = 0;
17770  int variable_count = 0;
17771  int min_variable_count = 0;
17772  float min_fixed_width = 0.0f;
17773  float total_fixed_width = 0.0f;
17774  float max_variable_width = 0.0f;
17775 
17776  NK_ASSERT(ctx);
17777  NK_ASSERT(ctx->current);
17778  NK_ASSERT(ctx->current->layout);
17779  if (!ctx || !ctx->current || !ctx->current->layout)
17780  return;
17781 
17782  win = ctx->current;
17783  layout = win->layout;
17784  NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
17785  if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
17786  for (i = 0; i < layout->row.columns; ++i) {
17787  float width = layout->row.templates[i];
17788  if (width >= 0.0f) {
17789  total_fixed_width += width;
17790  min_fixed_width += width;
17791  } else if (width < -1.0f) {
17792  width = -width;
17793  total_fixed_width += width;
17794  max_variable_width = NK_MAX(max_variable_width, width);
17795  variable_count++;
17796  } else {
17797  min_variable_count++;
17798  variable_count++;
17799  }
17800  }
17801  if (variable_count) {
17802  float space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type,
17803  layout->bounds.w, layout->row.columns);
17804  float var_width = (NK_MAX(space-min_fixed_width,0.0f)) / (float)variable_count;
17805  int enough_space = var_width >= max_variable_width;
17806  if (!enough_space)
17807  var_width = (NK_MAX(space-total_fixed_width,0)) / (float)min_variable_count;
17808  for (i = 0; i < layout->row.columns; ++i) {
17809  float *width = &layout->row.templates[i];
17810  *width = (*width >= 0.0f)? *width: (*width < -1.0f && !enough_space)? -(*width): var_width;
17811  }
17812  }
17813 }
17814 NK_API void
17815 nk_layout_space_begin(struct nk_context *ctx, enum nk_layout_format fmt,
17816  float height, int widget_count)
17817 {
17818  struct nk_window *win;
17819  struct nk_panel *layout;
17820 
17821  NK_ASSERT(ctx);
17822  NK_ASSERT(ctx->current);
17823  NK_ASSERT(ctx->current->layout);
17824  if (!ctx || !ctx->current || !ctx->current->layout)
17825  return;
17826 
17827  win = ctx->current;
17828  layout = win->layout;
17829  nk_panel_layout(ctx, win, height, widget_count);
17830  if (fmt == NK_STATIC)
17831  layout->row.type = NK_LAYOUT_STATIC_FREE;
17832  else layout->row.type = NK_LAYOUT_DYNAMIC_FREE;
17833 
17834  layout->row.ratio = 0;
17835  layout->row.filled = 0;
17836  layout->row.item_width = 0;
17837  layout->row.item_offset = 0;
17838 }
17839 NK_API void
17840 nk_layout_space_end(struct nk_context *ctx)
17841 {
17842  struct nk_window *win;
17843  struct nk_panel *layout;
17844 
17845  NK_ASSERT(ctx);
17846  NK_ASSERT(ctx->current);
17847  NK_ASSERT(ctx->current->layout);
17848  if (!ctx || !ctx->current || !ctx->current->layout)
17849  return;
17850 
17851  win = ctx->current;
17852  layout = win->layout;
17853  layout->row.item_width = 0;
17854  layout->row.item_height = 0;
17855  layout->row.item_offset = 0;
17856  nk_zero(&layout->row.item, sizeof(layout->row.item));
17857 }
17858 NK_API void
17859 nk_layout_space_push(struct nk_context *ctx, struct nk_rect rect)
17860 {
17861  struct nk_window *win;
17862  struct nk_panel *layout;
17863 
17864  NK_ASSERT(ctx);
17865  NK_ASSERT(ctx->current);
17866  NK_ASSERT(ctx->current->layout);
17867  if (!ctx || !ctx->current || !ctx->current->layout)
17868  return;
17869 
17870  win = ctx->current;
17871  layout = win->layout;
17872  layout->row.item = rect;
17873 }
17874 NK_API struct nk_rect
17876 {
17877  struct nk_rect ret;
17878  struct nk_window *win;
17879  struct nk_panel *layout;
17880 
17881  NK_ASSERT(ctx);
17882  NK_ASSERT(ctx->current);
17883  NK_ASSERT(ctx->current->layout);
17884  win = ctx->current;
17885  layout = win->layout;
17886 
17887  ret.x = layout->clip.x;
17888  ret.y = layout->clip.y;
17889  ret.w = layout->clip.w;
17890  ret.h = layout->row.height;
17891  return ret;
17892 }
17893 NK_API struct nk_rect
17895 {
17896  struct nk_rect ret;
17897  struct nk_window *win;
17898  struct nk_panel *layout;
17899 
17900  NK_ASSERT(ctx);
17901  NK_ASSERT(ctx->current);
17902  NK_ASSERT(ctx->current->layout);
17903  win = ctx->current;
17904  layout = win->layout;
17905 
17906  ret.x = layout->at_x;
17907  ret.y = layout->at_y;
17908  ret.w = layout->bounds.w - NK_MAX(layout->at_x - layout->bounds.x,0);
17909  ret.h = layout->row.height;
17910  return ret;
17911 }
17912 NK_API struct nk_vec2
17913 nk_layout_space_to_screen(struct nk_context *ctx, struct nk_vec2 ret)
17914 {
17915  struct nk_window *win;
17916  struct nk_panel *layout;
17917 
17918  NK_ASSERT(ctx);
17919  NK_ASSERT(ctx->current);
17920  NK_ASSERT(ctx->current->layout);
17921  win = ctx->current;
17922  layout = win->layout;
17923 
17924  ret.x += layout->at_x - (float)*layout->offset_x;
17925  ret.y += layout->at_y - (float)*layout->offset_y;
17926  return ret;
17927 }
17928 NK_API struct nk_vec2
17929 nk_layout_space_to_local(struct nk_context *ctx, struct nk_vec2 ret)
17930 {
17931  struct nk_window *win;
17932  struct nk_panel *layout;
17933 
17934  NK_ASSERT(ctx);
17935  NK_ASSERT(ctx->current);
17936  NK_ASSERT(ctx->current->layout);
17937  win = ctx->current;
17938  layout = win->layout;
17939 
17940  ret.x += -layout->at_x + (float)*layout->offset_x;
17941  ret.y += -layout->at_y + (float)*layout->offset_y;
17942  return ret;
17943 }
17944 NK_API struct nk_rect
17945 nk_layout_space_rect_to_screen(struct nk_context *ctx, struct nk_rect ret)
17946 {
17947  struct nk_window *win;
17948  struct nk_panel *layout;
17949 
17950  NK_ASSERT(ctx);
17951  NK_ASSERT(ctx->current);
17952  NK_ASSERT(ctx->current->layout);
17953  win = ctx->current;
17954  layout = win->layout;
17955 
17956  ret.x += layout->at_x - (float)*layout->offset_x;
17957  ret.y += layout->at_y - (float)*layout->offset_y;
17958  return ret;
17959 }
17960 NK_API struct nk_rect
17961 nk_layout_space_rect_to_local(struct nk_context *ctx, struct nk_rect ret)
17962 {
17963  struct nk_window *win;
17964  struct nk_panel *layout;
17965 
17966  NK_ASSERT(ctx);
17967  NK_ASSERT(ctx->current);
17968  NK_ASSERT(ctx->current->layout);
17969  win = ctx->current;
17970  layout = win->layout;
17971 
17972  ret.x += -layout->at_x + (float)*layout->offset_x;
17973  ret.y += -layout->at_y + (float)*layout->offset_y;
17974  return ret;
17975 }
17976 NK_LIB void
17977 nk_panel_alloc_row(const struct nk_context *ctx, struct nk_window *win)
17978 {
17979  struct nk_panel *layout = win->layout;
17980  struct nk_vec2 spacing = ctx->style.window.spacing;
17981  const float row_height = layout->row.height - spacing.y;
17982  nk_panel_layout(ctx, win, row_height, layout->row.columns);
17983 }
17984 NK_LIB void
17985 nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx,
17986  struct nk_window *win, int modify)
17987 {
17988  struct nk_panel *layout;
17989  const struct nk_style *style;
17990 
17991  struct nk_vec2 spacing;
17992  struct nk_vec2 padding;
17993 
17994  float item_offset = 0;
17995  float item_width = 0;
17996  float item_spacing = 0;
17997  float panel_space = 0;
17998 
17999  NK_ASSERT(ctx);
18000  NK_ASSERT(ctx->current);
18001  NK_ASSERT(ctx->current->layout);
18002  if (!ctx || !ctx->current || !ctx->current->layout)
18003  return;
18004 
18005  win = ctx->current;
18006  layout = win->layout;
18007  style = &ctx->style;
18008  NK_ASSERT(bounds);
18009 
18010  spacing = style->window.spacing;
18011  padding = nk_panel_get_padding(style, layout->type);
18012  panel_space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type,
18013  layout->bounds.w, layout->row.columns);
18014 
18015  /* calculate the width of one item inside the current layout space */
18016  switch (layout->row.type) {
18017  case NK_LAYOUT_DYNAMIC_FIXED: {
18018  /* scaling fixed size widgets item width */
18019  item_width = NK_MAX(1.0f,panel_space) / (float)layout->row.columns;
18020  item_offset = (float)layout->row.index * item_width;
18021  item_spacing = (float)layout->row.index * spacing.x;
18022  } break;
18023  case NK_LAYOUT_DYNAMIC_ROW: {
18024  /* scaling single ratio widget width */
18025  item_width = layout->row.item_width * panel_space;
18026  item_offset = layout->row.item_offset;
18027  item_spacing = 0;
18028 
18029  if (modify) {
18030  layout->row.item_offset += item_width + spacing.x;
18031  layout->row.filled += layout->row.item_width;
18032  layout->row.index = 0;
18033  }
18034  } break;
18035  case NK_LAYOUT_DYNAMIC_FREE: {
18036  /* panel width depended free widget placing */
18037  bounds->x = layout->at_x + (layout->bounds.w * layout->row.item.x);
18038  bounds->x -= (float)*layout->offset_x;
18039  bounds->y = layout->at_y + (layout->row.height * layout->row.item.y);
18040  bounds->y -= (float)*layout->offset_y;
18041  bounds->w = layout->bounds.w * layout->row.item.w;
18042  bounds->h = layout->row.height * layout->row.item.h;
18043  return;
18044  }
18045  case NK_LAYOUT_DYNAMIC: {
18046  /* scaling arrays of panel width ratios for every widget */
18047  float ratio;
18048  NK_ASSERT(layout->row.ratio);
18049  ratio = (layout->row.ratio[layout->row.index] < 0) ?
18050  layout->row.item_width : layout->row.ratio[layout->row.index];
18051 
18052  item_spacing = (float)layout->row.index * spacing.x;
18053  item_width = (ratio * panel_space);
18054  item_offset = layout->row.item_offset;
18055 
18056  if (modify) {
18057  layout->row.item_offset += item_width;
18058  layout->row.filled += ratio;
18059  }
18060  } break;
18061  case NK_LAYOUT_STATIC_FIXED: {
18062  /* non-scaling fixed widgets item width */
18063  item_width = layout->row.item_width;
18064  item_offset = (float)layout->row.index * item_width;
18065  item_spacing = (float)layout->row.index * spacing.x;
18066  } break;
18067  case NK_LAYOUT_STATIC_ROW: {
18068  /* scaling single ratio widget width */
18069  item_width = layout->row.item_width;
18070  item_offset = layout->row.item_offset;
18071  item_spacing = (float)layout->row.index * spacing.x;
18072  if (modify) layout->row.item_offset += item_width;
18073  } break;
18074  case NK_LAYOUT_STATIC_FREE: {
18075  /* free widget placing */
18076  bounds->x = layout->at_x + layout->row.item.x;
18077  bounds->w = layout->row.item.w;
18078  if (((bounds->x + bounds->w) > layout->max_x) && modify)
18079  layout->max_x = (bounds->x + bounds->w);
18080  bounds->x -= (float)*layout->offset_x;
18081  bounds->y = layout->at_y + layout->row.item.y;
18082  bounds->y -= (float)*layout->offset_y;
18083  bounds->h = layout->row.item.h;
18084  return;
18085  }
18086  case NK_LAYOUT_STATIC: {
18087  /* non-scaling array of panel pixel width for every widget */
18088  item_spacing = (float)layout->row.index * spacing.x;
18089  item_width = layout->row.ratio[layout->row.index];
18090  item_offset = layout->row.item_offset;
18091  if (modify) layout->row.item_offset += item_width;
18092  } break;
18093  case NK_LAYOUT_TEMPLATE: {
18094  /* stretchy row layout with combined dynamic/static widget width*/
18095  NK_ASSERT(layout->row.index < layout->row.columns);
18096  NK_ASSERT(layout->row.index < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
18097  item_width = layout->row.templates[layout->row.index];
18098  item_offset = layout->row.item_offset;
18099  item_spacing = (float)layout->row.index * spacing.x;
18100  if (modify) layout->row.item_offset += item_width;
18101  } break;
18102  default: NK_ASSERT(0); break;
18103  };
18104 
18105  /* set the bounds of the newly allocated widget */
18106  bounds->w = item_width;
18107  bounds->h = layout->row.height - spacing.y;
18108  bounds->y = layout->at_y - (float)*layout->offset_y;
18109  bounds->x = layout->at_x + item_offset + item_spacing + padding.x;
18110  if (((bounds->x + bounds->w) > layout->max_x) && modify)
18111  layout->max_x = bounds->x + bounds->w;
18112  bounds->x -= (float)*layout->offset_x;
18113 }
18114 NK_LIB void
18115 nk_panel_alloc_space(struct nk_rect *bounds, const struct nk_context *ctx)
18116 {
18117  struct nk_window *win;
18118  struct nk_panel *layout;
18119 
18120  NK_ASSERT(ctx);
18121  NK_ASSERT(ctx->current);
18122  NK_ASSERT(ctx->current->layout);
18123  if (!ctx || !ctx->current || !ctx->current->layout)
18124  return;
18125 
18126  /* check if the end of the row has been hit and begin new row if so */
18127  win = ctx->current;
18128  layout = win->layout;
18129  if (layout->row.index >= layout->row.columns)
18130  nk_panel_alloc_row(ctx, win);
18131 
18132  /* calculate widget position and size */
18133  nk_layout_widget_space(bounds, ctx, win, nk_true);
18134  layout->row.index++;
18135 }
18136 NK_LIB void
18137 nk_layout_peek(struct nk_rect *bounds, struct nk_context *ctx)
18138 {
18139  float y;
18140  int index;
18141  struct nk_window *win;
18142  struct nk_panel *layout;
18143 
18144  NK_ASSERT(ctx);
18145  NK_ASSERT(ctx->current);
18146  NK_ASSERT(ctx->current->layout);
18147  if (!ctx || !ctx->current || !ctx->current->layout)
18148  return;
18149 
18150  win = ctx->current;
18151  layout = win->layout;
18152  y = layout->at_y;
18153  index = layout->row.index;
18154  if (layout->row.index >= layout->row.columns) {
18155  layout->at_y += layout->row.height;
18156  layout->row.index = 0;
18157  }
18158  nk_layout_widget_space(bounds, ctx, win, nk_false);
18159  if (!layout->row.index) {
18160  bounds->x -= layout->row.item_offset;
18161  }
18162  layout->at_y = y;
18163  layout->row.index = index;
18164 }
18165 
18166 
18167 
18168 
18169 
18170 /* ===============================================================
18171  *
18172  * TREE
18173  *
18174  * ===============================================================*/
18175 NK_INTERN int
18176 nk_tree_state_base(struct nk_context *ctx, enum nk_tree_type type,
18177  struct nk_image *img, const char *title, enum nk_collapse_states *state)
18178 {
18179  struct nk_window *win;
18180  struct nk_panel *layout;
18181  const struct nk_style *style;
18182  struct nk_command_buffer *out;
18183  const struct nk_input *in;
18184  const struct nk_style_button *button;
18185  enum nk_symbol_type symbol;
18186  float row_height;
18187 
18188  struct nk_vec2 item_spacing;
18189  struct nk_rect header = {0,0,0,0};
18190  struct nk_rect sym = {0,0,0,0};
18191  struct nk_text text;
18192 
18193  nk_flags ws = 0;
18194  enum nk_widget_layout_states widget_state;
18195 
18196  NK_ASSERT(ctx);
18197  NK_ASSERT(ctx->current);
18198  NK_ASSERT(ctx->current->layout);
18199  if (!ctx || !ctx->current || !ctx->current->layout)
18200  return 0;
18201 
18202  /* cache some data */
18203  win = ctx->current;
18204  layout = win->layout;
18205  out = &win->buffer;
18206  style = &ctx->style;
18207  item_spacing = style->window.spacing;
18208 
18209  /* calculate header bounds and draw background */
18210  row_height = style->font->height + 2 * style->tab.padding.y;
18211  nk_layout_set_min_row_height(ctx, row_height);
18212  nk_layout_row_dynamic(ctx, row_height, 1);
18214 
18215  widget_state = nk_widget(&header, ctx);
18216  if (type == NK_TREE_TAB) {
18217  const struct nk_style_item *background = &style->tab.background;
18218  if (background->type == NK_STYLE_ITEM_IMAGE) {
18219  nk_draw_image(out, header, &background->data.image, nk_white);
18220  text.background = nk_rgba(0,0,0,0);
18221  } else {
18222  text.background = background->data.color;
18223  nk_fill_rect(out, header, 0, style->tab.border_color);
18224  nk_fill_rect(out, nk_shrink_rect(header, style->tab.border),
18225  style->tab.rounding, background->data.color);
18226  }
18227  } else text.background = style->window.background;
18228 
18229  /* update node state */
18230  in = (!(layout->flags & NK_WINDOW_ROM)) ? &ctx->input: 0;
18231  in = (in && widget_state == NK_WIDGET_VALID) ? &ctx->input : 0;
18232  if (nk_button_behavior(&ws, header, in, NK_BUTTON_DEFAULT))
18233  *state = (*state == NK_MAXIMIZED) ? NK_MINIMIZED : NK_MAXIMIZED;
18234 
18235  /* select correct button style */
18236  if (*state == NK_MAXIMIZED) {
18237  symbol = style->tab.sym_maximize;
18238  if (type == NK_TREE_TAB)
18239  button = &style->tab.tab_maximize_button;
18240  else button = &style->tab.node_maximize_button;
18241  } else {
18242  symbol = style->tab.sym_minimize;
18243  if (type == NK_TREE_TAB)
18244  button = &style->tab.tab_minimize_button;
18245  else button = &style->tab.node_minimize_button;
18246  }
18247 
18248  {/* draw triangle button */
18249  sym.w = sym.h = style->font->height;
18250  sym.y = header.y + style->tab.padding.y;
18251  sym.x = header.x + style->tab.padding.x;
18252  nk_do_button_symbol(&ws, &win->buffer, sym, symbol, NK_BUTTON_DEFAULT,
18253  button, 0, style->font);
18254 
18255  if (img) {
18256  /* draw optional image icon */
18257  sym.x = sym.x + sym.w + 4 * item_spacing.x;
18258  nk_draw_image(&win->buffer, sym, img, nk_white);
18259  sym.w = style->font->height + style->tab.spacing.x;}
18260  }
18261 
18262  {/* draw label */
18263  struct nk_rect label;
18264  header.w = NK_MAX(header.w, sym.w + item_spacing.x);
18265  label.x = sym.x + sym.w + item_spacing.x;
18266  label.y = sym.y;
18267  label.w = header.w - (sym.w + item_spacing.y + style->tab.indent);
18268  label.h = style->font->height;
18269  text.text = style->tab.text;
18270  text.padding = nk_vec2(0,0);
18271  nk_widget_text(out, label, title, nk_strlen(title), &text,
18272  NK_TEXT_LEFT, style->font);}
18273 
18274  /* increase x-axis cursor widget position pointer */
18275  if (*state == NK_MAXIMIZED) {
18276  layout->at_x = header.x + (float)*layout->offset_x + style->tab.indent;
18277  layout->bounds.w = NK_MAX(layout->bounds.w, style->tab.indent);
18278  layout->bounds.w -= (style->tab.indent + style->window.padding.x);
18279  layout->row.tree_depth++;
18280  return nk_true;
18281  } else return nk_false;
18282 }
18283 NK_INTERN int
18284 nk_tree_base(struct nk_context *ctx, enum nk_tree_type type,
18285  struct nk_image *img, const char *title, enum nk_collapse_states initial_state,
18286  const char *hash, int len, int line)
18287 {
18288  struct nk_window *win = ctx->current;
18289  int title_len = 0;
18290  nk_hash tree_hash = 0;
18291  nk_uint *state = 0;
18292 
18293  /* retrieve tree state from internal widget state tables */
18294  if (!hash) {
18295  title_len = (int)nk_strlen(title);
18296  tree_hash = nk_murmur_hash(title, (int)title_len, (nk_hash)line);
18297  } else tree_hash = nk_murmur_hash(hash, len, (nk_hash)line);
18298  state = nk_find_value(win, tree_hash);
18299  if (!state) {
18300  state = nk_add_value(ctx, win, tree_hash, 0);
18301  *state = initial_state;
18302  }
18303  return nk_tree_state_base(ctx, type, img, title, (enum nk_collapse_states*)state);
18304 }
18305 NK_API int
18306 nk_tree_state_push(struct nk_context *ctx, enum nk_tree_type type,
18307  const char *title, enum nk_collapse_states *state)
18308 {
18309  return nk_tree_state_base(ctx, type, 0, title, state);
18310 }
18311 NK_API int
18312 nk_tree_state_image_push(struct nk_context *ctx, enum nk_tree_type type,
18313  struct nk_image img, const char *title, enum nk_collapse_states *state)
18314 {
18315  return nk_tree_state_base(ctx, type, &img, title, state);
18316 }
18317 NK_API void
18318 nk_tree_state_pop(struct nk_context *ctx)
18319 {
18320  struct nk_window *win = 0;
18321  struct nk_panel *layout = 0;
18322 
18323  NK_ASSERT(ctx);
18324  NK_ASSERT(ctx->current);
18325  NK_ASSERT(ctx->current->layout);
18326  if (!ctx || !ctx->current || !ctx->current->layout)
18327  return;
18328 
18329  win = ctx->current;
18330  layout = win->layout;
18331  layout->at_x -= ctx->style.tab.indent + ctx->style.window.padding.x;
18332  layout->bounds.w += ctx->style.tab.indent + ctx->style.window.padding.x;
18333  NK_ASSERT(layout->row.tree_depth);
18334  layout->row.tree_depth--;
18335 }
18336 NK_API int
18338  const char *title, enum nk_collapse_states initial_state,
18339  const char *hash, int len, int line)
18340 {
18341  return nk_tree_base(ctx, type, 0, title, initial_state, hash, len, line);
18342 }
18343 NK_API int
18345  struct nk_image img, const char *title, enum nk_collapse_states initial_state,
18346  const char *hash, int len,int seed)
18347 {
18348  return nk_tree_base(ctx, type, &img, title, initial_state, hash, len, seed);
18349 }
18350 NK_API void
18351 nk_tree_pop(struct nk_context *ctx)
18352 {
18353  nk_tree_state_pop(ctx);
18354 }
18355 NK_INTERN int
18356 nk_tree_element_image_push_hashed_base(struct nk_context *ctx, enum nk_tree_type type,
18357  struct nk_image *img, const char *title, int title_len,
18358  enum nk_collapse_states *state, int *selected)
18359 {
18360  struct nk_window *win;
18361  struct nk_panel *layout;
18362  const struct nk_style *style;
18363  struct nk_command_buffer *out;
18364  const struct nk_input *in;
18365  const struct nk_style_button *button;
18366  enum nk_symbol_type symbol;
18367  float row_height;
18368  struct nk_vec2 padding;
18369 
18370  int text_len;
18371  float text_width;
18372 
18373  struct nk_vec2 item_spacing;
18374  struct nk_rect header = {0,0,0,0};
18375  struct nk_rect sym = {0,0,0,0};
18376  struct nk_text text;
18377 
18378  nk_flags ws = 0;
18379  enum nk_widget_layout_states widget_state;
18380 
18381  NK_ASSERT(ctx);
18382  NK_ASSERT(ctx->current);
18383  NK_ASSERT(ctx->current->layout);
18384  if (!ctx || !ctx->current || !ctx->current->layout)
18385  return 0;
18386 
18387  /* cache some data */
18388  win = ctx->current;
18389  layout = win->layout;
18390  out = &win->buffer;
18391  style = &ctx->style;
18392  item_spacing = style->window.spacing;
18393  padding = style->selectable.padding;
18394 
18395  /* calculate header bounds and draw background */
18396  row_height = style->font->height + 2 * style->tab.padding.y;
18397  nk_layout_set_min_row_height(ctx, row_height);
18398  nk_layout_row_dynamic(ctx, row_height, 1);
18400 
18401  widget_state = nk_widget(&header, ctx);
18402  if (type == NK_TREE_TAB) {
18403  const struct nk_style_item *background = &style->tab.background;
18404  if (background->type == NK_STYLE_ITEM_IMAGE) {
18405  nk_draw_image(out, header, &background->data.image, nk_white);
18406  text.background = nk_rgba(0,0,0,0);
18407  } else {
18408  text.background = background->data.color;
18409  nk_fill_rect(out, header, 0, style->tab.border_color);
18410  nk_fill_rect(out, nk_shrink_rect(header, style->tab.border),
18411  style->tab.rounding, background->data.color);
18412  }
18413  } else text.background = style->window.background;
18414 
18415  in = (!(layout->flags & NK_WINDOW_ROM)) ? &ctx->input: 0;
18416  in = (in && widget_state == NK_WIDGET_VALID) ? &ctx->input : 0;
18417 
18418  /* select correct button style */
18419  if (*state == NK_MAXIMIZED) {
18420  symbol = style->tab.sym_maximize;
18421  if (type == NK_TREE_TAB)
18422  button = &style->tab.tab_maximize_button;
18423  else button = &style->tab.node_maximize_button;
18424  } else {
18425  symbol = style->tab.sym_minimize;
18426  if (type == NK_TREE_TAB)
18427  button = &style->tab.tab_minimize_button;
18428  else button = &style->tab.node_minimize_button;
18429  }
18430  {/* draw triangle button */
18431  sym.w = sym.h = style->font->height;
18432  sym.y = header.y + style->tab.padding.y;
18433  sym.x = header.x + style->tab.padding.x;
18434  if (nk_do_button_symbol(&ws, &win->buffer, sym, symbol, NK_BUTTON_DEFAULT, button, in, style->font))
18435  *state = (*state == NK_MAXIMIZED) ? NK_MINIMIZED : NK_MAXIMIZED;}
18436 
18437  /* draw label */
18438  {nk_flags dummy = 0;
18439  struct nk_rect label;
18440  /* calculate size of the text and tooltip */
18441  text_len = nk_strlen(title);
18442  text_width = style->font->width(style->font->userdata, style->font->height, title, text_len);
18443  text_width += (4 * padding.x);
18444 
18445  header.w = NK_MAX(header.w, sym.w + item_spacing.x);
18446  label.x = sym.x + sym.w + item_spacing.x;
18447  label.y = sym.y;
18448  label.w = NK_MIN(header.w - (sym.w + item_spacing.y + style->tab.indent), text_width);
18449  label.h = style->font->height;
18450 
18451  if (img) {
18452  nk_do_selectable_image(&dummy, &win->buffer, label, title, title_len, NK_TEXT_LEFT,
18453  selected, img, &style->selectable, in, style->font);
18454  } else nk_do_selectable(&dummy, &win->buffer, label, title, title_len, NK_TEXT_LEFT,
18455  selected, &style->selectable, in, style->font);
18456  }
18457  /* increase x-axis cursor widget position pointer */
18458  if (*state == NK_MAXIMIZED) {
18459  layout->at_x = header.x + (float)*layout->offset_x + style->tab.indent;
18460  layout->bounds.w = NK_MAX(layout->bounds.w, style->tab.indent);
18461  layout->bounds.w -= (style->tab.indent + style->window.padding.x);
18462  layout->row.tree_depth++;
18463  return nk_true;
18464  } else return nk_false;
18465 }
18466 NK_INTERN int
18467 nk_tree_element_base(struct nk_context *ctx, enum nk_tree_type type,
18468  struct nk_image *img, const char *title, enum nk_collapse_states initial_state,
18469  int *selected, const char *hash, int len, int line)
18470 {
18471  struct nk_window *win = ctx->current;
18472  int title_len = 0;
18473  nk_hash tree_hash = 0;
18474  nk_uint *state = 0;
18475 
18476  /* retrieve tree state from internal widget state tables */
18477  if (!hash) {
18478  title_len = (int)nk_strlen(title);
18479  tree_hash = nk_murmur_hash(title, (int)title_len, (nk_hash)line);
18480  } else tree_hash = nk_murmur_hash(hash, len, (nk_hash)line);
18481  state = nk_find_value(win, tree_hash);
18482  if (!state) {
18483  state = nk_add_value(ctx, win, tree_hash, 0);
18484  *state = initial_state;
18485  } return nk_tree_element_image_push_hashed_base(ctx, type, img, title,
18486  nk_strlen(title), (enum nk_collapse_states*)state, selected);
18487 }
18488 NK_API int
18489 nk_tree_element_push_hashed(struct nk_context *ctx, enum nk_tree_type type,
18490  const char *title, enum nk_collapse_states initial_state,
18491  int *selected, const char *hash, int len, int seed)
18492 {
18493  return nk_tree_element_base(ctx, type, 0, title, initial_state, selected, hash, len, seed);
18494 }
18495 NK_API int
18497  struct nk_image img, const char *title, enum nk_collapse_states initial_state,
18498  int *selected, const char *hash, int len,int seed)
18499 {
18500  return nk_tree_element_base(ctx, type, &img, title, initial_state, selected, hash, len, seed);
18501 }
18502 NK_API void
18503 nk_tree_element_pop(struct nk_context *ctx)
18504 {
18505  nk_tree_state_pop(ctx);
18506 }
18507 
18508 
18509 
18510 
18511 
18512 /* ===============================================================
18513  *
18514  * GROUP
18515  *
18516  * ===============================================================*/
18517 NK_API int
18519  nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags)
18520 {
18521  struct nk_rect bounds;
18522  struct nk_window panel;
18523  struct nk_window *win;
18524 
18525  win = ctx->current;
18526  nk_panel_alloc_space(&bounds, ctx);
18527  {const struct nk_rect *c = &win->layout->clip;
18528  if (!NK_INTERSECT(c->x, c->y, c->w, c->h, bounds.x, bounds.y, bounds.w, bounds.h) &&
18529  !(flags & NK_WINDOW_MOVABLE)) {
18530  return 0;
18531  }}
18532  if (win->flags & NK_WINDOW_ROM)
18533  flags |= NK_WINDOW_ROM;
18534 
18535  /* initialize a fake window to create the panel from */
18536  nk_zero(&panel, sizeof(panel));
18537  panel.bounds = bounds;
18538  panel.flags = flags;
18539  panel.scrollbar.x = *x_offset;
18540  panel.scrollbar.y = *y_offset;
18541  panel.buffer = win->buffer;
18542  panel.layout = (struct nk_panel*)nk_create_panel(ctx);
18543  ctx->current = &panel;
18544  nk_panel_begin(ctx, (flags & NK_WINDOW_TITLE) ? title: 0, NK_PANEL_GROUP);
18545 
18546  win->buffer = panel.buffer;
18547  win->buffer.clip = panel.layout->clip;
18548  panel.layout->offset_x = x_offset;
18549  panel.layout->offset_y = y_offset;
18550  panel.layout->parent = win->layout;
18551  win->layout = panel.layout;
18552 
18553  ctx->current = win;
18554  if ((panel.layout->flags & NK_WINDOW_CLOSED) ||
18555  (panel.layout->flags & NK_WINDOW_MINIMIZED))
18556  {
18557  nk_flags f = panel.layout->flags;
18558  nk_group_scrolled_end(ctx);
18559  if (f & NK_WINDOW_CLOSED)
18560  return NK_WINDOW_CLOSED;
18561  if (f & NK_WINDOW_MINIMIZED)
18562  return NK_WINDOW_MINIMIZED;
18563  }
18564  return 1;
18565 }
18566 NK_API void
18567 nk_group_scrolled_end(struct nk_context *ctx)
18568 {
18569  struct nk_window *win;
18570  struct nk_panel *parent;
18571  struct nk_panel *g;
18572 
18573  struct nk_rect clip;
18574  struct nk_window pan;
18575  struct nk_vec2 panel_padding;
18576 
18577  NK_ASSERT(ctx);
18578  NK_ASSERT(ctx->current);
18579  if (!ctx || !ctx->current)
18580  return;
18581 
18582  /* make sure nk_group_begin was called correctly */
18583  NK_ASSERT(ctx->current);
18584  win = ctx->current;
18585  NK_ASSERT(win->layout);
18586  g = win->layout;
18587  NK_ASSERT(g->parent);
18588  parent = g->parent;
18589 
18590  /* dummy window */
18591  nk_zero_struct(pan);
18592  panel_padding = nk_panel_get_padding(&ctx->style, NK_PANEL_GROUP);
18593  pan.bounds.y = g->bounds.y - (g->header_height + g->menu.h);
18594  pan.bounds.x = g->bounds.x - panel_padding.x;
18595  pan.bounds.w = g->bounds.w + 2 * panel_padding.x;
18596  pan.bounds.h = g->bounds.h + g->header_height + g->menu.h;
18597  if (g->flags & NK_WINDOW_BORDER) {
18598  pan.bounds.x -= g->border;
18599  pan.bounds.y -= g->border;
18600  pan.bounds.w += 2*g->border;
18601  pan.bounds.h += 2*g->border;
18602  }
18603  if (!(g->flags & NK_WINDOW_NO_SCROLLBAR)) {
18604  pan.bounds.w += ctx->style.window.scrollbar_size.x;
18605  pan.bounds.h += ctx->style.window.scrollbar_size.y;
18606  }
18607  pan.scrollbar.x = *g->offset_x;
18608  pan.scrollbar.y = *g->offset_y;
18609  pan.flags = g->flags;
18610  pan.buffer = win->buffer;
18611  pan.layout = g;
18612  pan.parent = win;
18613  ctx->current = &pan;
18614 
18615  /* make sure group has correct clipping rectangle */
18616  nk_unify(&clip, &parent->clip, pan.bounds.x, pan.bounds.y,
18617  pan.bounds.x + pan.bounds.w, pan.bounds.y + pan.bounds.h + panel_padding.x);
18618  nk_push_scissor(&pan.buffer, clip);
18619  nk_end(ctx);
18620 
18621  win->buffer = pan.buffer;
18622  nk_push_scissor(&win->buffer, parent->clip);
18623  ctx->current = win;
18624  win->layout = parent;
18625  g->bounds = pan.bounds;
18626  return;
18627 }
18628 NK_API int
18630  struct nk_scroll *scroll, const char *title, nk_flags flags)
18631 {
18632  return nk_group_scrolled_offset_begin(ctx, &scroll->x, &scroll->y, title, flags);
18633 }
18634 NK_API int
18635 nk_group_begin_titled(struct nk_context *ctx, const char *id,
18636  const char *title, nk_flags flags)
18637 {
18638  int id_len;
18639  nk_hash id_hash;
18640  struct nk_window *win;
18641  nk_uint *x_offset;
18642  nk_uint *y_offset;
18643 
18644  NK_ASSERT(ctx);
18645  NK_ASSERT(id);
18646  NK_ASSERT(ctx->current);
18647  NK_ASSERT(ctx->current->layout);
18648  if (!ctx || !ctx->current || !ctx->current->layout || !id)
18649  return 0;
18650 
18651  /* find persistent group scrollbar value */
18652  win = ctx->current;
18653  id_len = (int)nk_strlen(id);
18654  id_hash = nk_murmur_hash(id, (int)id_len, NK_PANEL_GROUP);
18655  x_offset = nk_find_value(win, id_hash);
18656  if (!x_offset) {
18657  x_offset = nk_add_value(ctx, win, id_hash, 0);
18658  y_offset = nk_add_value(ctx, win, id_hash+1, 0);
18659 
18660  NK_ASSERT(x_offset);
18661  NK_ASSERT(y_offset);
18662  if (!x_offset || !y_offset) return 0;
18663  *x_offset = *y_offset = 0;
18664  } else y_offset = nk_find_value(win, id_hash+1);
18665  return nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags);
18666 }
18667 NK_API int
18668 nk_group_begin(struct nk_context *ctx, const char *title, nk_flags flags)
18669 {
18670  return nk_group_begin_titled(ctx, title, title, flags);
18671 }
18672 NK_API void
18673 nk_group_end(struct nk_context *ctx)
18674 {
18675  nk_group_scrolled_end(ctx);
18676 }
18677 
18678 
18679 
18680 
18681 
18682 /* ===============================================================
18683  *
18684  * LIST VIEW
18685  *
18686  * ===============================================================*/
18687 NK_API int
18688 nk_list_view_begin(struct nk_context *ctx, struct nk_list_view *view,
18689  const char *title, nk_flags flags, int row_height, int row_count)
18690 {
18691  int title_len;
18692  nk_hash title_hash;
18693  nk_uint *x_offset;
18694  nk_uint *y_offset;
18695 
18696  int result;
18697  struct nk_window *win;
18698  struct nk_panel *layout;
18699  const struct nk_style *style;
18700  struct nk_vec2 item_spacing;
18701 
18702  NK_ASSERT(ctx);
18703  NK_ASSERT(view);
18704  NK_ASSERT(title);
18705  if (!ctx || !view || !title) return 0;
18706 
18707  win = ctx->current;
18708  style = &ctx->style;
18709  item_spacing = style->window.spacing;
18710  row_height += NK_MAX(0, (int)item_spacing.y);
18711 
18712  /* find persistent list view scrollbar offset */
18713  title_len = (int)nk_strlen(title);
18714  title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_GROUP);
18715  x_offset = nk_find_value(win, title_hash);
18716  if (!x_offset) {
18717  x_offset = nk_add_value(ctx, win, title_hash, 0);
18718  y_offset = nk_add_value(ctx, win, title_hash+1, 0);
18719 
18720  NK_ASSERT(x_offset);
18721  NK_ASSERT(y_offset);
18722  if (!x_offset || !y_offset) return 0;
18723  *x_offset = *y_offset = 0;
18724  } else y_offset = nk_find_value(win, title_hash+1);
18725  view->scroll_value = *y_offset;
18726  view->scroll_pointer = y_offset;
18727 
18728  *y_offset = 0;
18729  result = nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags);
18730  win = ctx->current;
18731  layout = win->layout;
18732 
18733  view->total_height = row_height * NK_MAX(row_count,1);
18734  view->begin = (int)NK_MAX(((float)view->scroll_value / (float)row_height), 0.0f);
18735  view->count = (int)NK_MAX(nk_iceilf((layout->clip.h)/(float)row_height),0);
18736  view->count = NK_MIN(view->count, row_count - view->begin);
18737  view->end = view->begin + view->count;
18738  view->ctx = ctx;
18739  return result;
18740 }
18741 NK_API void
18742 nk_list_view_end(struct nk_list_view *view)
18743 {
18744  struct nk_context *ctx;
18745  struct nk_window *win;
18746  struct nk_panel *layout;
18747 
18748  NK_ASSERT(view);
18749  NK_ASSERT(view->ctx);
18750  NK_ASSERT(view->scroll_pointer);
18751  if (!view || !view->ctx) return;
18752 
18753  ctx = view->ctx;
18754  win = ctx->current;
18755  layout = win->layout;
18756  layout->at_y = layout->bounds.y + (float)view->total_height;
18757  *view->scroll_pointer = *view->scroll_pointer + view->scroll_value;
18758  nk_group_end(view->ctx);
18759 }
18760 
18761 
18762 
18763 
18764 
18765 /* ===============================================================
18766  *
18767  * WIDGET
18768  *
18769  * ===============================================================*/
18770 NK_API struct nk_rect
18771 nk_widget_bounds(struct nk_context *ctx)
18772 {
18773  struct nk_rect bounds;
18774  NK_ASSERT(ctx);
18775  NK_ASSERT(ctx->current);
18776  if (!ctx || !ctx->current)
18777  return nk_rect(0,0,0,0);
18778  nk_layout_peek(&bounds, ctx);
18779  return bounds;
18780 }
18781 NK_API struct nk_vec2
18782 nk_widget_position(struct nk_context *ctx)
18783 {
18784  struct nk_rect bounds;
18785  NK_ASSERT(ctx);
18786  NK_ASSERT(ctx->current);
18787  if (!ctx || !ctx->current)
18788  return nk_vec2(0,0);
18789 
18790  nk_layout_peek(&bounds, ctx);
18791  return nk_vec2(bounds.x, bounds.y);
18792 }
18793 NK_API struct nk_vec2
18794 nk_widget_size(struct nk_context *ctx)
18795 {
18796  struct nk_rect bounds;
18797  NK_ASSERT(ctx);
18798  NK_ASSERT(ctx->current);
18799  if (!ctx || !ctx->current)
18800  return nk_vec2(0,0);
18801 
18802  nk_layout_peek(&bounds, ctx);
18803  return nk_vec2(bounds.w, bounds.h);
18804 }
18805 NK_API float
18806 nk_widget_width(struct nk_context *ctx)
18807 {
18808  struct nk_rect bounds;
18809  NK_ASSERT(ctx);
18810  NK_ASSERT(ctx->current);
18811  if (!ctx || !ctx->current)
18812  return 0;
18813 
18814  nk_layout_peek(&bounds, ctx);
18815  return bounds.w;
18816 }
18817 NK_API float
18818 nk_widget_height(struct nk_context *ctx)
18819 {
18820  struct nk_rect bounds;
18821  NK_ASSERT(ctx);
18822  NK_ASSERT(ctx->current);
18823  if (!ctx || !ctx->current)
18824  return 0;
18825 
18826  nk_layout_peek(&bounds, ctx);
18827  return bounds.h;
18828 }
18829 NK_API int
18830 nk_widget_is_hovered(struct nk_context *ctx)
18831 {
18832  struct nk_rect c, v;
18833  struct nk_rect bounds;
18834  NK_ASSERT(ctx);
18835  NK_ASSERT(ctx->current);
18836  if (!ctx || !ctx->current || ctx->active != ctx->current)
18837  return 0;
18838 
18839  c = ctx->current->layout->clip;
18840  c.x = (float)((int)c.x);
18841  c.y = (float)((int)c.y);
18842  c.w = (float)((int)c.w);
18843  c.h = (float)((int)c.h);
18844 
18845  nk_layout_peek(&bounds, ctx);
18846  nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h);
18847  if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h))
18848  return 0;
18849  return nk_input_is_mouse_hovering_rect(&ctx->input, bounds);
18850 }
18851 NK_API int
18852 nk_widget_is_mouse_clicked(struct nk_context *ctx, enum nk_buttons btn)
18853 {
18854  struct nk_rect c, v;
18855  struct nk_rect bounds;
18856  NK_ASSERT(ctx);
18857  NK_ASSERT(ctx->current);
18858  if (!ctx || !ctx->current || ctx->active != ctx->current)
18859  return 0;
18860 
18861  c = ctx->current->layout->clip;
18862  c.x = (float)((int)c.x);
18863  c.y = (float)((int)c.y);
18864  c.w = (float)((int)c.w);
18865  c.h = (float)((int)c.h);
18866 
18867  nk_layout_peek(&bounds, ctx);
18868  nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h);
18869  if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h))
18870  return 0;
18871  return nk_input_mouse_clicked(&ctx->input, btn, bounds);
18872 }
18873 NK_API int
18874 nk_widget_has_mouse_click_down(struct nk_context *ctx, enum nk_buttons btn, int down)
18875 {
18876  struct nk_rect c, v;
18877  struct nk_rect bounds;
18878  NK_ASSERT(ctx);
18879  NK_ASSERT(ctx->current);
18880  if (!ctx || !ctx->current || ctx->active != ctx->current)
18881  return 0;
18882 
18883  c = ctx->current->layout->clip;
18884  c.x = (float)((int)c.x);
18885  c.y = (float)((int)c.y);
18886  c.w = (float)((int)c.w);
18887  c.h = (float)((int)c.h);
18888 
18889  nk_layout_peek(&bounds, ctx);
18890  nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h);
18891  if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h))
18892  return 0;
18893  return nk_input_has_mouse_click_down_in_rect(&ctx->input, btn, bounds, down);
18894 }
18896 nk_widget(struct nk_rect *bounds, const struct nk_context *ctx)
18897 {
18898  struct nk_rect c, v;
18899  struct nk_window *win;
18900  struct nk_panel *layout;
18901  const struct nk_input *in;
18902 
18903  NK_ASSERT(ctx);
18904  NK_ASSERT(ctx->current);
18905  NK_ASSERT(ctx->current->layout);
18906  if (!ctx || !ctx->current || !ctx->current->layout)
18907  return NK_WIDGET_INVALID;
18908 
18909  /* allocate space and check if the widget needs to be updated and drawn */
18910  nk_panel_alloc_space(bounds, ctx);
18911  win = ctx->current;
18912  layout = win->layout;
18913  in = &ctx->input;
18914  c = layout->clip;
18915 
18916  /* if one of these triggers you forgot to add an `if` condition around either
18917  a window, group, popup, combobox or contextual menu `begin` and `end` block.
18918  Example:
18919  if (nk_begin(...) {...} nk_end(...); or
18920  if (nk_group_begin(...) { nk_group_end(...);} */
18921  NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED));
18922  NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN));
18923  NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED));
18924 
18925  /* need to convert to int here to remove floating point errors */
18926  bounds->x = (float)((int)bounds->x);
18927  bounds->y = (float)((int)bounds->y);
18928  bounds->w = (float)((int)bounds->w);
18929  bounds->h = (float)((int)bounds->h);
18930 
18931  c.x = (float)((int)c.x);
18932  c.y = (float)((int)c.y);
18933  c.w = (float)((int)c.w);
18934  c.h = (float)((int)c.h);
18935 
18936  nk_unify(&v, &c, bounds->x, bounds->y, bounds->x + bounds->w, bounds->y + bounds->h);
18937  if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds->x, bounds->y, bounds->w, bounds->h))
18938  return NK_WIDGET_INVALID;
18939  if (!NK_INBOX(in->mouse.pos.x, in->mouse.pos.y, v.x, v.y, v.w, v.h))
18940  return NK_WIDGET_ROM;
18941  return NK_WIDGET_VALID;
18942 }
18944 nk_widget_fitting(struct nk_rect *bounds, struct nk_context *ctx,
18945  struct nk_vec2 item_padding)
18946 {
18947  /* update the bounds to stand without padding */
18948  struct nk_window *win;
18949  struct nk_style *style;
18950  struct nk_panel *layout;
18951  enum nk_widget_layout_states state;
18952  struct nk_vec2 panel_padding;
18953 
18954  NK_ASSERT(ctx);
18955  NK_ASSERT(ctx->current);
18956  NK_ASSERT(ctx->current->layout);
18957  if (!ctx || !ctx->current || !ctx->current->layout)
18958  return NK_WIDGET_INVALID;
18959 
18960  win = ctx->current;
18961  style = &ctx->style;
18962  layout = win->layout;
18963  state = nk_widget(bounds, ctx);
18964 
18965  panel_padding = nk_panel_get_padding(style, layout->type);
18966  if (layout->row.index == 1) {
18967  bounds->w += panel_padding.x;
18968  bounds->x -= panel_padding.x;
18969  } else bounds->x -= item_padding.x;
18970 
18971  if (layout->row.index == layout->row.columns)
18972  bounds->w += panel_padding.x;
18973  else bounds->w += item_padding.x;
18974  return state;
18975 }
18976 NK_API void
18977 nk_spacing(struct nk_context *ctx, int cols)
18978 {
18979  struct nk_window *win;
18980  struct nk_panel *layout;
18981  struct nk_rect none;
18982  int i, index, rows;
18983 
18984  NK_ASSERT(ctx);
18985  NK_ASSERT(ctx->current);
18986  NK_ASSERT(ctx->current->layout);
18987  if (!ctx || !ctx->current || !ctx->current->layout)
18988  return;
18989 
18990  /* spacing over row boundaries */
18991  win = ctx->current;
18992  layout = win->layout;
18993  index = (layout->row.index + cols) % layout->row.columns;
18994  rows = (layout->row.index + cols) / layout->row.columns;
18995  if (rows) {
18996  for (i = 0; i < rows; ++i)
18997  nk_panel_alloc_row(ctx, win);
18998  cols = index;
18999  }
19000  /* non table layout need to allocate space */
19001  if (layout->row.type != NK_LAYOUT_DYNAMIC_FIXED &&
19002  layout->row.type != NK_LAYOUT_STATIC_FIXED) {
19003  for (i = 0; i < cols; ++i)
19004  nk_panel_alloc_space(&none, ctx);
19005  } layout->row.index = index;
19006 }
19007 
19008 
19009 
19010 
19011 
19012 /* ===============================================================
19013  *
19014  * TEXT
19015  *
19016  * ===============================================================*/
19017 NK_LIB void
19018 nk_widget_text(struct nk_command_buffer *o, struct nk_rect b,
19019  const char *string, int len, const struct nk_text *t,
19020  nk_flags a, const struct nk_user_font *f)
19021 {
19022  struct nk_rect label;
19023  float text_width;
19024 
19025  NK_ASSERT(o);
19026  NK_ASSERT(t);
19027  if (!o || !t) return;
19028 
19029  b.h = NK_MAX(b.h, 2 * t->padding.y);
19030  label.x = 0; label.w = 0;
19031  label.y = b.y + t->padding.y;
19032  label.h = NK_MIN(f->height, b.h - 2 * t->padding.y);
19033 
19034  text_width = f->width(f->userdata, f->height, (const char*)string, len);
19035  text_width += (2.0f * t->padding.x);
19036 
19037  /* align in x-axis */
19038  if (a & NK_TEXT_ALIGN_LEFT) {
19039  label.x = b.x + t->padding.x;
19040  label.w = NK_MAX(0, b.w - 2 * t->padding.x);
19041  } else if (a & NK_TEXT_ALIGN_CENTERED) {
19042  label.w = NK_MAX(1, 2 * t->padding.x + (float)text_width);
19043  label.x = (b.x + t->padding.x + ((b.w - 2 * t->padding.x) - label.w) / 2);
19044  label.x = NK_MAX(b.x + t->padding.x, label.x);
19045  label.w = NK_MIN(b.x + b.w, label.x + label.w);
19046  if (label.w >= label.x) label.w -= label.x;
19047  } else if (a & NK_TEXT_ALIGN_RIGHT) {
19048  label.x = NK_MAX(b.x + t->padding.x, (b.x + b.w) - (2 * t->padding.x + (float)text_width));
19049  label.w = (float)text_width + 2 * t->padding.x;
19050  } else return;
19051 
19052  /* align in y-axis */
19053  if (a & NK_TEXT_ALIGN_MIDDLE) {
19054  label.y = b.y + b.h/2.0f - (float)f->height/2.0f;
19055  label.h = NK_MAX(b.h/2.0f, b.h - (b.h/2.0f + f->height/2.0f));
19056  } else if (a & NK_TEXT_ALIGN_BOTTOM) {
19057  label.y = b.y + b.h - f->height;
19058  label.h = f->height;
19059  }
19060  nk_draw_text(o, label, (const char*)string, len, f, t->background, t->text);
19061 }
19062 NK_LIB void
19063 nk_widget_text_wrap(struct nk_command_buffer *o, struct nk_rect b,
19064  const char *string, int len, const struct nk_text *t,
19065  const struct nk_user_font *f)
19066 {
19067  float width;
19068  int glyphs = 0;
19069  int fitting = 0;
19070  int done = 0;
19071  struct nk_rect line;
19072  struct nk_text text;
19073  NK_INTERN nk_rune seperator[] = {' '};
19074 
19075  NK_ASSERT(o);
19076  NK_ASSERT(t);
19077  if (!o || !t) return;
19078 
19079  text.padding = nk_vec2(0,0);
19080  text.background = t->background;
19081  text.text = t->text;
19082 
19083  b.w = NK_MAX(b.w, 2 * t->padding.x);
19084  b.h = NK_MAX(b.h, 2 * t->padding.y);
19085  b.h = b.h - 2 * t->padding.y;
19086 
19087  line.x = b.x + t->padding.x;
19088  line.y = b.y + t->padding.y;
19089  line.w = b.w - 2 * t->padding.x;
19090  line.h = 2 * t->padding.y + f->height;
19091 
19092  fitting = nk_text_clamp(f, string, len, line.w, &glyphs, &width, seperator,NK_LEN(seperator));
19093  while (done < len) {
19094  if (!fitting || line.y + line.h >= (b.y + b.h)) break;
19095  nk_widget_text(o, line, &string[done], fitting, &text, NK_TEXT_LEFT, f);
19096  done += fitting;
19097  line.y += f->height + 2 * t->padding.y;
19098  fitting = nk_text_clamp(f, &string[done], len - done, line.w, &glyphs, &width, seperator,NK_LEN(seperator));
19099  }
19100 }
19101 NK_API void
19102 nk_text_colored(struct nk_context *ctx, const char *str, int len,
19103  nk_flags alignment, struct nk_color color)
19104 {
19105  struct nk_window *win;
19106  const struct nk_style *style;
19107 
19108  struct nk_vec2 item_padding;
19109  struct nk_rect bounds;
19110  struct nk_text text;
19111 
19112  NK_ASSERT(ctx);
19113  NK_ASSERT(ctx->current);
19114  NK_ASSERT(ctx->current->layout);
19115  if (!ctx || !ctx->current || !ctx->current->layout) return;
19116 
19117  win = ctx->current;
19118  style = &ctx->style;
19119  nk_panel_alloc_space(&bounds, ctx);
19120  item_padding = style->text.padding;
19121 
19122  text.padding.x = item_padding.x;
19123  text.padding.y = item_padding.y;
19124  text.background = style->window.background;
19125  text.text = color;
19126  nk_widget_text(&win->buffer, bounds, str, len, &text, alignment, style->font);
19127 }
19128 NK_API void
19129 nk_text_wrap_colored(struct nk_context *ctx, const char *str,
19130  int len, struct nk_color color)
19131 {
19132  struct nk_window *win;
19133  const struct nk_style *style;
19134 
19135  struct nk_vec2 item_padding;
19136  struct nk_rect bounds;
19137  struct nk_text text;
19138 
19139  NK_ASSERT(ctx);
19140  NK_ASSERT(ctx->current);
19141  NK_ASSERT(ctx->current->layout);
19142  if (!ctx || !ctx->current || !ctx->current->layout) return;
19143 
19144  win = ctx->current;
19145  style = &ctx->style;
19146  nk_panel_alloc_space(&bounds, ctx);
19147  item_padding = style->text.padding;
19148 
19149  text.padding.x = item_padding.x;
19150  text.padding.y = item_padding.y;
19151  text.background = style->window.background;
19152  text.text = color;
19153  nk_widget_text_wrap(&win->buffer, bounds, str, len, &text, style->font);
19154 }
19155 #ifdef NK_INCLUDE_STANDARD_VARARGS
19156 NK_API void
19157 nk_labelf_colored(struct nk_context *ctx, nk_flags flags,
19158  struct nk_color color, const char *fmt, ...)
19159 {
19160  va_list args;
19161  va_start(args, fmt);
19162  nk_labelfv_colored(ctx, flags, color, fmt, args);
19163  va_end(args);
19164 }
19165 NK_API void
19166 nk_labelf_colored_wrap(struct nk_context *ctx, struct nk_color color,
19167  const char *fmt, ...)
19168 {
19169  va_list args;
19170  va_start(args, fmt);
19171  nk_labelfv_colored_wrap(ctx, color, fmt, args);
19172  va_end(args);
19173 }
19174 NK_API void
19175 nk_labelf(struct nk_context *ctx, nk_flags flags, const char *fmt, ...)
19176 {
19177  va_list args;
19178  va_start(args, fmt);
19179  nk_labelfv(ctx, flags, fmt, args);
19180  va_end(args);
19181 }
19182 NK_API void
19183 nk_labelf_wrap(struct nk_context *ctx, const char *fmt,...)
19184 {
19185  va_list args;
19186  va_start(args, fmt);
19187  nk_labelfv_wrap(ctx, fmt, args);
19188  va_end(args);
19189 }
19190 NK_API void
19191 nk_labelfv_colored(struct nk_context *ctx, nk_flags flags,
19192  struct nk_color color, const char *fmt, va_list args)
19193 {
19194  char buf[256];
19195  nk_strfmt(buf, NK_LEN(buf), fmt, args);
19196  nk_label_colored(ctx, buf, flags, color);
19197 }
19198 
19199 NK_API void
19200 nk_labelfv_colored_wrap(struct nk_context *ctx, struct nk_color color,
19201  const char *fmt, va_list args)
19202 {
19203  char buf[256];
19204  nk_strfmt(buf, NK_LEN(buf), fmt, args);
19205  nk_label_colored_wrap(ctx, buf, color);
19206 }
19207 
19208 NK_API void
19209 nk_labelfv(struct nk_context *ctx, nk_flags flags, const char *fmt, va_list args)
19210 {
19211  char buf[256];
19212  nk_strfmt(buf, NK_LEN(buf), fmt, args);
19213  nk_label(ctx, buf, flags);
19214 }
19215 
19216 NK_API void
19217 nk_labelfv_wrap(struct nk_context *ctx, const char *fmt, va_list args)
19218 {
19219  char buf[256];
19220  nk_strfmt(buf, NK_LEN(buf), fmt, args);
19221  nk_label_wrap(ctx, buf);
19222 }
19223 
19224 NK_API void
19225 nk_value_bool(struct nk_context *ctx, const char *prefix, int value)
19226 {
19227  nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, ((value) ? "true": "false"));
19228 }
19229 NK_API void
19230 nk_value_int(struct nk_context *ctx, const char *prefix, int value)
19231 {
19232  nk_labelf(ctx, NK_TEXT_LEFT, "%s: %d", prefix, value);
19233 }
19234 NK_API void
19235 nk_value_uint(struct nk_context *ctx, const char *prefix, unsigned int value)
19236 {
19237  nk_labelf(ctx, NK_TEXT_LEFT, "%s: %u", prefix, value);
19238 }
19239 NK_API void
19240 nk_value_float(struct nk_context *ctx, const char *prefix, float value)
19241 {
19242  double double_value = (double)value;
19243  nk_labelf(ctx, NK_TEXT_LEFT, "%s: %.3f", prefix, double_value);
19244 }
19245 NK_API void
19246 nk_value_color_byte(struct nk_context *ctx, const char *p, struct nk_color c)
19247 {
19248  nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%d, %d, %d, %d)", p, c.r, c.g, c.b, c.a);
19249 }
19250 NK_API void
19251 nk_value_color_float(struct nk_context *ctx, const char *p, struct nk_color color)
19252 {
19253  double c[4]; nk_color_dv(c, color);
19254  nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%.2f, %.2f, %.2f, %.2f)",
19255  p, c[0], c[1], c[2], c[3]);
19256 }
19257 NK_API void
19258 nk_value_color_hex(struct nk_context *ctx, const char *prefix, struct nk_color color)
19259 {
19260  char hex[16];
19261  nk_color_hex_rgba(hex, color);
19262  nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, hex);
19263 }
19264 #endif
19265 NK_API void
19266 nk_text(struct nk_context *ctx, const char *str, int len, nk_flags alignment)
19267 {
19268  NK_ASSERT(ctx);
19269  if (!ctx) return;
19270  nk_text_colored(ctx, str, len, alignment, ctx->style.text.color);
19271 }
19272 NK_API void
19273 nk_text_wrap(struct nk_context *ctx, const char *str, int len)
19274 {
19275  NK_ASSERT(ctx);
19276  if (!ctx) return;
19277  nk_text_wrap_colored(ctx, str, len, ctx->style.text.color);
19278 }
19279 NK_API void
19280 nk_label(struct nk_context *ctx, const char *str, nk_flags alignment)
19281 {
19282  nk_text(ctx, str, nk_strlen(str), alignment);
19283 }
19284 NK_API void
19285 nk_label_colored(struct nk_context *ctx, const char *str, nk_flags align,
19286  struct nk_color color)
19287 {
19288  nk_text_colored(ctx, str, nk_strlen(str), align, color);
19289 }
19290 NK_API void
19291 nk_label_wrap(struct nk_context *ctx, const char *str)
19292 {
19293  nk_text_wrap(ctx, str, nk_strlen(str));
19294 }
19295 NK_API void
19296 nk_label_colored_wrap(struct nk_context *ctx, const char *str, struct nk_color color)
19297 {
19298  nk_text_wrap_colored(ctx, str, nk_strlen(str), color);
19299 }
19300 
19301 
19302 
19303 
19304 
19305 /* ===============================================================
19306  *
19307  * IMAGE
19308  *
19309  * ===============================================================*/
19311 nk_handle_ptr(void *ptr)
19312 {
19313  nk_handle handle = {0};
19314  handle.ptr = ptr;
19315  return handle;
19316 }
19318 nk_handle_id(int id)
19319 {
19320  nk_handle handle;
19321  nk_zero_struct(handle);
19322  handle.id = id;
19323  return handle;
19324 }
19325 NK_API struct nk_image
19326 nk_subimage_ptr(void *ptr, unsigned short w, unsigned short h, struct nk_rect r)
19327 {
19328  struct nk_image s;
19329  nk_zero(&s, sizeof(s));
19330  s.handle.ptr = ptr;
19331  s.w = w; s.h = h;
19332  s.region[0] = (unsigned short)r.x;
19333  s.region[1] = (unsigned short)r.y;
19334  s.region[2] = (unsigned short)r.w;
19335  s.region[3] = (unsigned short)r.h;
19336  return s;
19337 }
19338 NK_API struct nk_image
19339 nk_subimage_id(int id, unsigned short w, unsigned short h, struct nk_rect r)
19340 {
19341  struct nk_image s;
19342  nk_zero(&s, sizeof(s));
19343  s.handle.id = id;
19344  s.w = w; s.h = h;
19345  s.region[0] = (unsigned short)r.x;
19346  s.region[1] = (unsigned short)r.y;
19347  s.region[2] = (unsigned short)r.w;
19348  s.region[3] = (unsigned short)r.h;
19349  return s;
19350 }
19351 NK_API struct nk_image
19352 nk_subimage_handle(nk_handle handle, unsigned short w, unsigned short h,
19353  struct nk_rect r)
19354 {
19355  struct nk_image s;
19356  nk_zero(&s, sizeof(s));
19357  s.handle = handle;
19358  s.w = w; s.h = h;
19359  s.region[0] = (unsigned short)r.x;
19360  s.region[1] = (unsigned short)r.y;
19361  s.region[2] = (unsigned short)r.w;
19362  s.region[3] = (unsigned short)r.h;
19363  return s;
19364 }
19365 NK_API struct nk_image
19367 {
19368  struct nk_image s;
19369  nk_zero(&s, sizeof(s));
19370  s.handle = handle;
19371  s.w = 0; s.h = 0;
19372  s.region[0] = 0;
19373  s.region[1] = 0;
19374  s.region[2] = 0;
19375  s.region[3] = 0;
19376  return s;
19377 }
19378 NK_API struct nk_image
19379 nk_image_ptr(void *ptr)
19380 {
19381  struct nk_image s;
19382  nk_zero(&s, sizeof(s));
19383  NK_ASSERT(ptr);
19384  s.handle.ptr = ptr;
19385  s.w = 0; s.h = 0;
19386  s.region[0] = 0;
19387  s.region[1] = 0;
19388  s.region[2] = 0;
19389  s.region[3] = 0;
19390  return s;
19391 }
19392 NK_API struct nk_image
19393 nk_image_id(int id)
19394 {
19395  struct nk_image s;
19396  nk_zero(&s, sizeof(s));
19397  s.handle.id = id;
19398  s.w = 0; s.h = 0;
19399  s.region[0] = 0;
19400  s.region[1] = 0;
19401  s.region[2] = 0;
19402  s.region[3] = 0;
19403  return s;
19404 }
19405 NK_API int
19406 nk_image_is_subimage(const struct nk_image* img)
19407 {
19408  NK_ASSERT(img);
19409  return !(img->w == 0 && img->h == 0);
19410 }
19411 NK_API void
19412 nk_image(struct nk_context *ctx, struct nk_image img)
19413 {
19414  struct nk_window *win;
19415  struct nk_rect bounds;
19416 
19417  NK_ASSERT(ctx);
19418  NK_ASSERT(ctx->current);
19419  NK_ASSERT(ctx->current->layout);
19420  if (!ctx || !ctx->current || !ctx->current->layout) return;
19421 
19422  win = ctx->current;
19423  if (!nk_widget(&bounds, ctx)) return;
19424  nk_draw_image(&win->buffer, bounds, &img, nk_white);
19425 }
19426 NK_API void
19427 nk_image_color(struct nk_context *ctx, struct nk_image img, struct nk_color col)
19428 {
19429  struct nk_window *win;
19430  struct nk_rect bounds;
19431 
19432  NK_ASSERT(ctx);
19433  NK_ASSERT(ctx->current);
19434  NK_ASSERT(ctx->current->layout);
19435  if (!ctx || !ctx->current || !ctx->current->layout) return;
19436 
19437  win = ctx->current;
19438  if (!nk_widget(&bounds, ctx)) return;
19439  nk_draw_image(&win->buffer, bounds, &img, col);
19440 }
19441 
19442 
19443 
19444 
19445 
19446 /* ==============================================================
19447  *
19448  * BUTTON
19449  *
19450  * ===============================================================*/
19451 NK_LIB void
19452 nk_draw_symbol(struct nk_command_buffer *out, enum nk_symbol_type type,
19453  struct nk_rect content, struct nk_color background, struct nk_color foreground,
19454  float border_width, const struct nk_user_font *font)
19455 {
19456  switch (type) {
19457  case NK_SYMBOL_X:
19458  case NK_SYMBOL_UNDERSCORE:
19459  case NK_SYMBOL_PLUS:
19460  case NK_SYMBOL_MINUS: {
19461  /* single character text symbol */
19462  const char *X = (type == NK_SYMBOL_X) ? "x":
19463  (type == NK_SYMBOL_UNDERSCORE) ? "_":
19464  (type == NK_SYMBOL_PLUS) ? "+": "-";
19465  struct nk_text text;
19466  text.padding = nk_vec2(0,0);
19467  text.background = background;
19468  text.text = foreground;
19469  nk_widget_text(out, content, X, 1, &text, NK_TEXT_CENTERED, font);
19470  } break;
19473  case NK_SYMBOL_RECT_SOLID:
19474  case NK_SYMBOL_RECT_OUTLINE: {
19475  /* simple empty/filled shapes */
19476  if (type == NK_SYMBOL_RECT_SOLID || type == NK_SYMBOL_RECT_OUTLINE) {
19477  nk_fill_rect(out, content, 0, foreground);
19478  if (type == NK_SYMBOL_RECT_OUTLINE)
19479  nk_fill_rect(out, nk_shrink_rect(content, border_width), 0, background);
19480  } else {
19481  nk_fill_circle(out, content, foreground);
19482  if (type == NK_SYMBOL_CIRCLE_OUTLINE)
19483  nk_fill_circle(out, nk_shrink_rect(content, 1), background);
19484  }
19485  } break;
19486  case NK_SYMBOL_TRIANGLE_UP:
19489  case NK_SYMBOL_TRIANGLE_RIGHT: {
19490  enum nk_heading heading;
19491  struct nk_vec2 points[3];
19492  heading = (type == NK_SYMBOL_TRIANGLE_RIGHT) ? NK_RIGHT :
19493  (type == NK_SYMBOL_TRIANGLE_LEFT) ? NK_LEFT:
19494  (type == NK_SYMBOL_TRIANGLE_UP) ? NK_UP: NK_DOWN;
19495  nk_triangle_from_direction(points, content, 0, 0, heading);
19496  nk_fill_triangle(out, points[0].x, points[0].y, points[1].x, points[1].y,
19497  points[2].x, points[2].y, foreground);
19498  } break;
19499  default:
19500  case NK_SYMBOL_NONE:
19501  case NK_SYMBOL_MAX: break;
19502  }
19503 }
19504 NK_LIB int
19505 nk_button_behavior(nk_flags *state, struct nk_rect r,
19506  const struct nk_input *i, enum nk_button_behavior behavior)
19507 {
19508  int ret = 0;
19509  nk_widget_state_reset(state);
19510  if (!i) return 0;
19511  if (nk_input_is_mouse_hovering_rect(i, r)) {
19512  *state = NK_WIDGET_STATE_HOVERED;
19514  *state = NK_WIDGET_STATE_ACTIVE;
19516  ret = (behavior != NK_BUTTON_DEFAULT) ?
19518 #ifdef NK_BUTTON_TRIGGER_ON_RELEASE
19520 #else
19522 #endif
19523  }
19524  }
19526  *state |= NK_WIDGET_STATE_ENTERED;
19527  else if (nk_input_is_mouse_prev_hovering_rect(i, r))
19528  *state |= NK_WIDGET_STATE_LEFT;
19529  return ret;
19530 }
19531 NK_LIB const struct nk_style_item*
19532 nk_draw_button(struct nk_command_buffer *out,
19533  const struct nk_rect *bounds, nk_flags state,
19534  const struct nk_style_button *style)
19535 {
19536  const struct nk_style_item *background;
19537  if (state & NK_WIDGET_STATE_HOVER)
19538  background = &style->hover;
19539  else if (state & NK_WIDGET_STATE_ACTIVED)
19540  background = &style->active;
19541  else background = &style->normal;
19542 
19543  if (background->type == NK_STYLE_ITEM_IMAGE) {
19544  nk_draw_image(out, *bounds, &background->data.image, nk_white);
19545  } else {
19546  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
19547  nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
19548  }
19549  return background;
19550 }
19551 NK_LIB int
19552 nk_do_button(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r,
19553  const struct nk_style_button *style, const struct nk_input *in,
19554  enum nk_button_behavior behavior, struct nk_rect *content)
19555 {
19556  struct nk_rect bounds;
19557  NK_ASSERT(style);
19558  NK_ASSERT(state);
19559  NK_ASSERT(out);
19560  if (!out || !style)
19561  return nk_false;
19562 
19563  /* calculate button content space */
19564  content->x = r.x + style->padding.x + style->border + style->rounding;
19565  content->y = r.y + style->padding.y + style->border + style->rounding;
19566  content->w = r.w - (2 * style->padding.x + style->border + style->rounding*2);
19567  content->h = r.h - (2 * style->padding.y + style->border + style->rounding*2);
19568 
19569  /* execute button behavior */
19570  bounds.x = r.x - style->touch_padding.x;
19571  bounds.y = r.y - style->touch_padding.y;
19572  bounds.w = r.w + 2 * style->touch_padding.x;
19573  bounds.h = r.h + 2 * style->touch_padding.y;
19574  return nk_button_behavior(state, bounds, in, behavior);
19575 }
19576 NK_LIB void
19577 nk_draw_button_text(struct nk_command_buffer *out,
19578  const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state,
19579  const struct nk_style_button *style, const char *txt, int len,
19580  nk_flags text_alignment, const struct nk_user_font *font)
19581 {
19582  struct nk_text text;
19583  const struct nk_style_item *background;
19584  background = nk_draw_button(out, bounds, state, style);
19585 
19586  /* select correct colors/images */
19587  if (background->type == NK_STYLE_ITEM_COLOR)
19588  text.background = background->data.color;
19589  else text.background = style->text_background;
19590  if (state & NK_WIDGET_STATE_HOVER)
19591  text.text = style->text_hover;
19592  else if (state & NK_WIDGET_STATE_ACTIVED)
19593  text.text = style->text_active;
19594  else text.text = style->text_normal;
19595 
19596  text.padding = nk_vec2(0,0);
19597  nk_widget_text(out, *content, txt, len, &text, text_alignment, font);
19598 }
19599 NK_LIB int
19600 nk_do_button_text(nk_flags *state,
19601  struct nk_command_buffer *out, struct nk_rect bounds,
19602  const char *string, int len, nk_flags align, enum nk_button_behavior behavior,
19603  const struct nk_style_button *style, const struct nk_input *in,
19604  const struct nk_user_font *font)
19605 {
19606  struct nk_rect content;
19607  int ret = nk_false;
19608 
19609  NK_ASSERT(state);
19610  NK_ASSERT(style);
19611  NK_ASSERT(out);
19612  NK_ASSERT(string);
19613  NK_ASSERT(font);
19614  if (!out || !style || !font || !string)
19615  return nk_false;
19616 
19617  ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
19618  if (style->draw_begin) style->draw_begin(out, style->userdata);
19619  nk_draw_button_text(out, &bounds, &content, *state, style, string, len, align, font);
19620  if (style->draw_end) style->draw_end(out, style->userdata);
19621  return ret;
19622 }
19623 NK_LIB void
19624 nk_draw_button_symbol(struct nk_command_buffer *out,
19625  const struct nk_rect *bounds, const struct nk_rect *content,
19626  nk_flags state, const struct nk_style_button *style,
19627  enum nk_symbol_type type, const struct nk_user_font *font)
19628 {
19629  struct nk_color sym, bg;
19630  const struct nk_style_item *background;
19631 
19632  /* select correct colors/images */
19633  background = nk_draw_button(out, bounds, state, style);
19634  if (background->type == NK_STYLE_ITEM_COLOR)
19635  bg = background->data.color;
19636  else bg = style->text_background;
19637 
19638  if (state & NK_WIDGET_STATE_HOVER)
19639  sym = style->text_hover;
19640  else if (state & NK_WIDGET_STATE_ACTIVED)
19641  sym = style->text_active;
19642  else sym = style->text_normal;
19643  nk_draw_symbol(out, type, *content, bg, sym, 1, font);
19644 }
19645 NK_LIB int
19646 nk_do_button_symbol(nk_flags *state,
19647  struct nk_command_buffer *out, struct nk_rect bounds,
19648  enum nk_symbol_type symbol, enum nk_button_behavior behavior,
19649  const struct nk_style_button *style, const struct nk_input *in,
19650  const struct nk_user_font *font)
19651 {
19652  int ret;
19653  struct nk_rect content;
19654 
19655  NK_ASSERT(state);
19656  NK_ASSERT(style);
19657  NK_ASSERT(font);
19658  NK_ASSERT(out);
19659  if (!out || !style || !font || !state)
19660  return nk_false;
19661 
19662  ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
19663  if (style->draw_begin) style->draw_begin(out, style->userdata);
19664  nk_draw_button_symbol(out, &bounds, &content, *state, style, symbol, font);
19665  if (style->draw_end) style->draw_end(out, style->userdata);
19666  return ret;
19667 }
19668 NK_LIB void
19669 nk_draw_button_image(struct nk_command_buffer *out,
19670  const struct nk_rect *bounds, const struct nk_rect *content,
19671  nk_flags state, const struct nk_style_button *style, const struct nk_image *img)
19672 {
19673  nk_draw_button(out, bounds, state, style);
19674  nk_draw_image(out, *content, img, nk_white);
19675 }
19676 NK_LIB int
19677 nk_do_button_image(nk_flags *state,
19678  struct nk_command_buffer *out, struct nk_rect bounds,
19679  struct nk_image img, enum nk_button_behavior b,
19680  const struct nk_style_button *style, const struct nk_input *in)
19681 {
19682  int ret;
19683  struct nk_rect content;
19684 
19685  NK_ASSERT(state);
19686  NK_ASSERT(style);
19687  NK_ASSERT(out);
19688  if (!out || !style || !state)
19689  return nk_false;
19690 
19691  ret = nk_do_button(state, out, bounds, style, in, b, &content);
19692  content.x += style->image_padding.x;
19693  content.y += style->image_padding.y;
19694  content.w -= 2 * style->image_padding.x;
19695  content.h -= 2 * style->image_padding.y;
19696 
19697  if (style->draw_begin) style->draw_begin(out, style->userdata);
19698  nk_draw_button_image(out, &bounds, &content, *state, style, &img);
19699  if (style->draw_end) style->draw_end(out, style->userdata);
19700  return ret;
19701 }
19702 NK_LIB void
19703 nk_draw_button_text_symbol(struct nk_command_buffer *out,
19704  const struct nk_rect *bounds, const struct nk_rect *label,
19705  const struct nk_rect *symbol, nk_flags state, const struct nk_style_button *style,
19706  const char *str, int len, enum nk_symbol_type type,
19707  const struct nk_user_font *font)
19708 {
19709  struct nk_color sym;
19710  struct nk_text text;
19711  const struct nk_style_item *background;
19712 
19713  /* select correct background colors/images */
19714  background = nk_draw_button(out, bounds, state, style);
19715  if (background->type == NK_STYLE_ITEM_COLOR)
19716  text.background = background->data.color;
19717  else text.background = style->text_background;
19718 
19719  /* select correct text colors */
19720  if (state & NK_WIDGET_STATE_HOVER) {
19721  sym = style->text_hover;
19722  text.text = style->text_hover;
19723  } else if (state & NK_WIDGET_STATE_ACTIVED) {
19724  sym = style->text_active;
19725  text.text = style->text_active;
19726  } else {
19727  sym = style->text_normal;
19728  text.text = style->text_normal;
19729  }
19730 
19731  text.padding = nk_vec2(0,0);
19732  nk_draw_symbol(out, type, *symbol, style->text_background, sym, 0, font);
19733  nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font);
19734 }
19735 NK_LIB int
19736 nk_do_button_text_symbol(nk_flags *state,
19737  struct nk_command_buffer *out, struct nk_rect bounds,
19738  enum nk_symbol_type symbol, const char *str, int len, nk_flags align,
19739  enum nk_button_behavior behavior, const struct nk_style_button *style,
19740  const struct nk_user_font *font, const struct nk_input *in)
19741 {
19742  int ret;
19743  struct nk_rect tri = {0,0,0,0};
19744  struct nk_rect content;
19745 
19746  NK_ASSERT(style);
19747  NK_ASSERT(out);
19748  NK_ASSERT(font);
19749  if (!out || !style || !font)
19750  return nk_false;
19751 
19752  ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
19753  tri.y = content.y + (content.h/2) - font->height/2;
19754  tri.w = font->height; tri.h = font->height;
19755  if (align & NK_TEXT_ALIGN_LEFT) {
19756  tri.x = (content.x + content.w) - (2 * style->padding.x + tri.w);
19757  tri.x = NK_MAX(tri.x, 0);
19758  } else tri.x = content.x + 2 * style->padding.x;
19759 
19760  /* draw button */
19761  if (style->draw_begin) style->draw_begin(out, style->userdata);
19762  nk_draw_button_text_symbol(out, &bounds, &content, &tri,
19763  *state, style, str, len, symbol, font);
19764  if (style->draw_end) style->draw_end(out, style->userdata);
19765  return ret;
19766 }
19767 NK_LIB void
19768 nk_draw_button_text_image(struct nk_command_buffer *out,
19769  const struct nk_rect *bounds, const struct nk_rect *label,
19770  const struct nk_rect *image, nk_flags state, const struct nk_style_button *style,
19771  const char *str, int len, const struct nk_user_font *font,
19772  const struct nk_image *img)
19773 {
19774  struct nk_text text;
19775  const struct nk_style_item *background;
19776  background = nk_draw_button(out, bounds, state, style);
19777 
19778  /* select correct colors */
19779  if (background->type == NK_STYLE_ITEM_COLOR)
19780  text.background = background->data.color;
19781  else text.background = style->text_background;
19782  if (state & NK_WIDGET_STATE_HOVER)
19783  text.text = style->text_hover;
19784  else if (state & NK_WIDGET_STATE_ACTIVED)
19785  text.text = style->text_active;
19786  else text.text = style->text_normal;
19787 
19788  text.padding = nk_vec2(0,0);
19789  nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font);
19790  nk_draw_image(out, *image, img, nk_white);
19791 }
19792 NK_LIB int
19793 nk_do_button_text_image(nk_flags *state,
19794  struct nk_command_buffer *out, struct nk_rect bounds,
19795  struct nk_image img, const char* str, int len, nk_flags align,
19796  enum nk_button_behavior behavior, const struct nk_style_button *style,
19797  const struct nk_user_font *font, const struct nk_input *in)
19798 {
19799  int ret;
19800  struct nk_rect icon;
19801  struct nk_rect content;
19802 
19803  NK_ASSERT(style);
19804  NK_ASSERT(state);
19805  NK_ASSERT(font);
19806  NK_ASSERT(out);
19807  if (!out || !font || !style || !str)
19808  return nk_false;
19809 
19810  ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
19811  icon.y = bounds.y + style->padding.y;
19812  icon.w = icon.h = bounds.h - 2 * style->padding.y;
19813  if (align & NK_TEXT_ALIGN_LEFT) {
19814  icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w);
19815  icon.x = NK_MAX(icon.x, 0);
19816  } else icon.x = bounds.x + 2 * style->padding.x;
19817 
19818  icon.x += style->image_padding.x;
19819  icon.y += style->image_padding.y;
19820  icon.w -= 2 * style->image_padding.x;
19821  icon.h -= 2 * style->image_padding.y;
19822 
19823  if (style->draw_begin) style->draw_begin(out, style->userdata);
19824  nk_draw_button_text_image(out, &bounds, &content, &icon, *state, style, str, len, font, &img);
19825  if (style->draw_end) style->draw_end(out, style->userdata);
19826  return ret;
19827 }
19828 NK_API void
19829 nk_button_set_behavior(struct nk_context *ctx, enum nk_button_behavior behavior)
19830 {
19831  NK_ASSERT(ctx);
19832  if (!ctx) return;
19833  ctx->button_behavior = behavior;
19834 }
19835 NK_API int
19836 nk_button_push_behavior(struct nk_context *ctx, enum nk_button_behavior behavior)
19837 {
19838  struct nk_config_stack_button_behavior *button_stack;
19839  struct nk_config_stack_button_behavior_element *element;
19840 
19841  NK_ASSERT(ctx);
19842  if (!ctx) return 0;
19843 
19844  button_stack = &ctx->stacks.button_behaviors;
19845  NK_ASSERT(button_stack->head < (int)NK_LEN(button_stack->elements));
19846  if (button_stack->head >= (int)NK_LEN(button_stack->elements))
19847  return 0;
19848 
19849  element = &button_stack->elements[button_stack->head++];
19850  element->address = &ctx->button_behavior;
19851  element->old_value = ctx->button_behavior;
19852  ctx->button_behavior = behavior;
19853  return 1;
19854 }
19855 NK_API int
19857 {
19858  struct nk_config_stack_button_behavior *button_stack;
19859  struct nk_config_stack_button_behavior_element *element;
19860 
19861  NK_ASSERT(ctx);
19862  if (!ctx) return 0;
19863 
19864  button_stack = &ctx->stacks.button_behaviors;
19865  NK_ASSERT(button_stack->head > 0);
19866  if (button_stack->head < 1)
19867  return 0;
19868 
19869  element = &button_stack->elements[--button_stack->head];
19870  *element->address = element->old_value;
19871  return 1;
19872 }
19873 NK_API int
19874 nk_button_text_styled(struct nk_context *ctx,
19875  const struct nk_style_button *style, const char *title, int len)
19876 {
19877  struct nk_window *win;
19878  struct nk_panel *layout;
19879  const struct nk_input *in;
19880 
19881  struct nk_rect bounds;
19882  enum nk_widget_layout_states state;
19883 
19884  NK_ASSERT(ctx);
19885  NK_ASSERT(style);
19886  NK_ASSERT(ctx->current);
19887  NK_ASSERT(ctx->current->layout);
19888  if (!style || !ctx || !ctx->current || !ctx->current->layout) return 0;
19889 
19890  win = ctx->current;
19891  layout = win->layout;
19892  state = nk_widget(&bounds, ctx);
19893 
19894  if (!state) return 0;
19895  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
19896  return nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds,
19897  title, len, style->text_alignment, ctx->button_behavior,
19898  style, in, ctx->style.font);
19899 }
19900 NK_API int
19901 nk_button_text(struct nk_context *ctx, const char *title, int len)
19902 {
19903  NK_ASSERT(ctx);
19904  if (!ctx) return 0;
19905  return nk_button_text_styled(ctx, &ctx->style.button, title, len);
19906 }
19907 NK_API int nk_button_label_styled(struct nk_context *ctx,
19908  const struct nk_style_button *style, const char *title)
19909 {
19910  return nk_button_text_styled(ctx, style, title, nk_strlen(title));
19911 }
19912 NK_API int nk_button_label(struct nk_context *ctx, const char *title)
19913 {
19914  return nk_button_text(ctx, title, nk_strlen(title));
19915 }
19916 NK_API int
19917 nk_button_color(struct nk_context *ctx, struct nk_color color)
19918 {
19919  struct nk_window *win;
19920  struct nk_panel *layout;
19921  const struct nk_input *in;
19922  struct nk_style_button button;
19923 
19924  int ret = 0;
19925  struct nk_rect bounds;
19926  struct nk_rect content;
19927  enum nk_widget_layout_states state;
19928 
19929  NK_ASSERT(ctx);
19930  NK_ASSERT(ctx->current);
19931  NK_ASSERT(ctx->current->layout);
19932  if (!ctx || !ctx->current || !ctx->current->layout)
19933  return 0;
19934 
19935  win = ctx->current;
19936  layout = win->layout;
19937 
19938  state = nk_widget(&bounds, ctx);
19939  if (!state) return 0;
19940  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
19941 
19942  button = ctx->style.button;
19943  button.normal = nk_style_item_color(color);
19944  button.hover = nk_style_item_color(color);
19945  button.active = nk_style_item_color(color);
19946  ret = nk_do_button(&ctx->last_widget_state, &win->buffer, bounds,
19947  &button, in, ctx->button_behavior, &content);
19948  nk_draw_button(&win->buffer, &bounds, ctx->last_widget_state, &button);
19949  return ret;
19950 }
19951 NK_API int
19953  const struct nk_style_button *style, enum nk_symbol_type symbol)
19954 {
19955  struct nk_window *win;
19956  struct nk_panel *layout;
19957  const struct nk_input *in;
19958 
19959  struct nk_rect bounds;
19960  enum nk_widget_layout_states state;
19961 
19962  NK_ASSERT(ctx);
19963  NK_ASSERT(ctx->current);
19964  NK_ASSERT(ctx->current->layout);
19965  if (!ctx || !ctx->current || !ctx->current->layout)
19966  return 0;
19967 
19968  win = ctx->current;
19969  layout = win->layout;
19970  state = nk_widget(&bounds, ctx);
19971  if (!state) return 0;
19972  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
19973  return nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, bounds,
19974  symbol, ctx->button_behavior, style, in, ctx->style.font);
19975 }
19976 NK_API int
19977 nk_button_symbol(struct nk_context *ctx, enum nk_symbol_type symbol)
19978 {
19979  NK_ASSERT(ctx);
19980  if (!ctx) return 0;
19981  return nk_button_symbol_styled(ctx, &ctx->style.button, symbol);
19982 }
19983 NK_API int
19984 nk_button_image_styled(struct nk_context *ctx, const struct nk_style_button *style,
19985  struct nk_image img)
19986 {
19987  struct nk_window *win;
19988  struct nk_panel *layout;
19989  const struct nk_input *in;
19990 
19991  struct nk_rect bounds;
19992  enum nk_widget_layout_states state;
19993 
19994  NK_ASSERT(ctx);
19995  NK_ASSERT(ctx->current);
19996  NK_ASSERT(ctx->current->layout);
19997  if (!ctx || !ctx->current || !ctx->current->layout)
19998  return 0;
19999 
20000  win = ctx->current;
20001  layout = win->layout;
20002 
20003  state = nk_widget(&bounds, ctx);
20004  if (!state) return 0;
20005  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20006  return nk_do_button_image(&ctx->last_widget_state, &win->buffer, bounds,
20007  img, ctx->button_behavior, style, in);
20008 }
20009 NK_API int
20010 nk_button_image(struct nk_context *ctx, struct nk_image img)
20011 {
20012  NK_ASSERT(ctx);
20013  if (!ctx) return 0;
20014  return nk_button_image_styled(ctx, &ctx->style.button, img);
20015 }
20016 NK_API int
20018  const struct nk_style_button *style, enum nk_symbol_type symbol,
20019  const char *text, int len, nk_flags align)
20020 {
20021  struct nk_window *win;
20022  struct nk_panel *layout;
20023  const struct nk_input *in;
20024 
20025  struct nk_rect bounds;
20026  enum nk_widget_layout_states state;
20027 
20028  NK_ASSERT(ctx);
20029  NK_ASSERT(ctx->current);
20030  NK_ASSERT(ctx->current->layout);
20031  if (!ctx || !ctx->current || !ctx->current->layout)
20032  return 0;
20033 
20034  win = ctx->current;
20035  layout = win->layout;
20036 
20037  state = nk_widget(&bounds, ctx);
20038  if (!state) return 0;
20039  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20040  return nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds,
20041  symbol, text, len, align, ctx->button_behavior,
20042  style, ctx->style.font, in);
20043 }
20044 NK_API int
20045 nk_button_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol,
20046  const char* text, int len, nk_flags align)
20047 {
20048  NK_ASSERT(ctx);
20049  if (!ctx) return 0;
20050  return nk_button_symbol_text_styled(ctx, &ctx->style.button, symbol, text, len, align);
20051 }
20052 NK_API int nk_button_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol,
20053  const char *label, nk_flags align)
20054 {
20055  return nk_button_symbol_text(ctx, symbol, label, nk_strlen(label), align);
20056 }
20058  const struct nk_style_button *style, enum nk_symbol_type symbol,
20059  const char *title, nk_flags align)
20060 {
20061  return nk_button_symbol_text_styled(ctx, style, symbol, title, nk_strlen(title), align);
20062 }
20063 NK_API int
20065  const struct nk_style_button *style, struct nk_image img, const char *text,
20066  int len, nk_flags align)
20067 {
20068  struct nk_window *win;
20069  struct nk_panel *layout;
20070  const struct nk_input *in;
20071 
20072  struct nk_rect bounds;
20073  enum nk_widget_layout_states state;
20074 
20075  NK_ASSERT(ctx);
20076  NK_ASSERT(ctx->current);
20077  NK_ASSERT(ctx->current->layout);
20078  if (!ctx || !ctx->current || !ctx->current->layout)
20079  return 0;
20080 
20081  win = ctx->current;
20082  layout = win->layout;
20083 
20084  state = nk_widget(&bounds, ctx);
20085  if (!state) return 0;
20086  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20087  return nk_do_button_text_image(&ctx->last_widget_state, &win->buffer,
20088  bounds, img, text, len, align, ctx->button_behavior,
20089  style, ctx->style.font, in);
20090 }
20091 NK_API int
20092 nk_button_image_text(struct nk_context *ctx, struct nk_image img,
20093  const char *text, int len, nk_flags align)
20094 {
20095  return nk_button_image_text_styled(ctx, &ctx->style.button,img, text, len, align);
20096 }
20097 NK_API int nk_button_image_label(struct nk_context *ctx, struct nk_image img,
20098  const char *label, nk_flags align)
20099 {
20100  return nk_button_image_text(ctx, img, label, nk_strlen(label), align);
20101 }
20103  const struct nk_style_button *style, struct nk_image img,
20104  const char *label, nk_flags text_alignment)
20105 {
20106  return nk_button_image_text_styled(ctx, style, img, label, nk_strlen(label), text_alignment);
20107 }
20108 
20109 
20110 
20111 
20112 
20113 /* ===============================================================
20114  *
20115  * TOGGLE
20116  *
20117  * ===============================================================*/
20118 NK_LIB int
20119 nk_toggle_behavior(const struct nk_input *in, struct nk_rect select,
20120  nk_flags *state, int active)
20121 {
20122  nk_widget_state_reset(state);
20123  if (nk_button_behavior(state, select, in, NK_BUTTON_DEFAULT)) {
20124  *state = NK_WIDGET_STATE_ACTIVE;
20125  active = !active;
20126  }
20127  if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, select))
20128  *state |= NK_WIDGET_STATE_ENTERED;
20129  else if (nk_input_is_mouse_prev_hovering_rect(in, select))
20130  *state |= NK_WIDGET_STATE_LEFT;
20131  return active;
20132 }
20133 NK_LIB void
20134 nk_draw_checkbox(struct nk_command_buffer *out,
20135  nk_flags state, const struct nk_style_toggle *style, int active,
20136  const struct nk_rect *label, const struct nk_rect *selector,
20137  const struct nk_rect *cursors, const char *string, int len,
20138  const struct nk_user_font *font)
20139 {
20140  const struct nk_style_item *background;
20141  const struct nk_style_item *cursor;
20142  struct nk_text text;
20143 
20144  /* select correct colors/images */
20145  if (state & NK_WIDGET_STATE_HOVER) {
20146  background = &style->hover;
20147  cursor = &style->cursor_hover;
20148  text.text = style->text_hover;
20149  } else if (state & NK_WIDGET_STATE_ACTIVED) {
20150  background = &style->hover;
20151  cursor = &style->cursor_hover;
20152  text.text = style->text_active;
20153  } else {
20154  background = &style->normal;
20155  cursor = &style->cursor_normal;
20156  text.text = style->text_normal;
20157  }
20158 
20159  /* draw background and cursor */
20160  if (background->type == NK_STYLE_ITEM_COLOR) {
20161  nk_fill_rect(out, *selector, 0, style->border_color);
20162  nk_fill_rect(out, nk_shrink_rect(*selector, style->border), 0, background->data.color);
20163  } else nk_draw_image(out, *selector, &background->data.image, nk_white);
20164  if (active) {
20165  if (cursor->type == NK_STYLE_ITEM_IMAGE)
20166  nk_draw_image(out, *cursors, &cursor->data.image, nk_white);
20167  else nk_fill_rect(out, *cursors, 0, cursor->data.color);
20168  }
20169 
20170  text.padding.x = 0;
20171  text.padding.y = 0;
20172  text.background = style->text_background;
20173  nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font);
20174 }
20175 NK_LIB void
20176 nk_draw_option(struct nk_command_buffer *out,
20177  nk_flags state, const struct nk_style_toggle *style, int active,
20178  const struct nk_rect *label, const struct nk_rect *selector,
20179  const struct nk_rect *cursors, const char *string, int len,
20180  const struct nk_user_font *font)
20181 {
20182  const struct nk_style_item *background;
20183  const struct nk_style_item *cursor;
20184  struct nk_text text;
20185 
20186  /* select correct colors/images */
20187  if (state & NK_WIDGET_STATE_HOVER) {
20188  background = &style->hover;
20189  cursor = &style->cursor_hover;
20190  text.text = style->text_hover;
20191  } else if (state & NK_WIDGET_STATE_ACTIVED) {
20192  background = &style->hover;
20193  cursor = &style->cursor_hover;
20194  text.text = style->text_active;
20195  } else {
20196  background = &style->normal;
20197  cursor = &style->cursor_normal;
20198  text.text = style->text_normal;
20199  }
20200 
20201  /* draw background and cursor */
20202  if (background->type == NK_STYLE_ITEM_COLOR) {
20203  nk_fill_circle(out, *selector, style->border_color);
20204  nk_fill_circle(out, nk_shrink_rect(*selector, style->border), background->data.color);
20205  } else nk_draw_image(out, *selector, &background->data.image, nk_white);
20206  if (active) {
20207  if (cursor->type == NK_STYLE_ITEM_IMAGE)
20208  nk_draw_image(out, *cursors, &cursor->data.image, nk_white);
20209  else nk_fill_circle(out, *cursors, cursor->data.color);
20210  }
20211 
20212  text.padding.x = 0;
20213  text.padding.y = 0;
20214  text.background = style->text_background;
20215  nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font);
20216 }
20217 NK_LIB int
20218 nk_do_toggle(nk_flags *state,
20219  struct nk_command_buffer *out, struct nk_rect r,
20220  int *active, const char *str, int len, enum nk_toggle_type type,
20221  const struct nk_style_toggle *style, const struct nk_input *in,
20222  const struct nk_user_font *font)
20223 {
20224  int was_active;
20225  struct nk_rect bounds;
20226  struct nk_rect select;
20227  struct nk_rect cursor;
20228  struct nk_rect label;
20229 
20230  NK_ASSERT(style);
20231  NK_ASSERT(out);
20232  NK_ASSERT(font);
20233  if (!out || !style || !font || !active)
20234  return 0;
20235 
20236  r.w = NK_MAX(r.w, font->height + 2 * style->padding.x);
20237  r.h = NK_MAX(r.h, font->height + 2 * style->padding.y);
20238 
20239  /* add additional touch padding for touch screen devices */
20240  bounds.x = r.x - style->touch_padding.x;
20241  bounds.y = r.y - style->touch_padding.y;
20242  bounds.w = r.w + 2 * style->touch_padding.x;
20243  bounds.h = r.h + 2 * style->touch_padding.y;
20244 
20245  /* calculate the selector space */
20246  select.w = font->height;
20247  select.h = select.w;
20248  select.y = r.y + r.h/2.0f - select.h/2.0f;
20249  select.x = r.x;
20250 
20251  /* calculate the bounds of the cursor inside the selector */
20252  cursor.x = select.x + style->padding.x + style->border;
20253  cursor.y = select.y + style->padding.y + style->border;
20254  cursor.w = select.w - (2 * style->padding.x + 2 * style->border);
20255  cursor.h = select.h - (2 * style->padding.y + 2 * style->border);
20256 
20257  /* label behind the selector */
20258  label.x = select.x + select.w + style->spacing;
20259  label.y = select.y;
20260  label.w = NK_MAX(r.x + r.w, label.x) - label.x;
20261  label.h = select.w;
20262 
20263  /* update selector */
20264  was_active = *active;
20265  *active = nk_toggle_behavior(in, bounds, state, *active);
20266 
20267  /* draw selector */
20268  if (style->draw_begin)
20269  style->draw_begin(out, style->userdata);
20270  if (type == NK_TOGGLE_CHECK) {
20271  nk_draw_checkbox(out, *state, style, *active, &label, &select, &cursor, str, len, font);
20272  } else {
20273  nk_draw_option(out, *state, style, *active, &label, &select, &cursor, str, len, font);
20274  }
20275  if (style->draw_end)
20276  style->draw_end(out, style->userdata);
20277  return (was_active != *active);
20278 }
20279 /*----------------------------------------------------------------
20280  *
20281  * CHECKBOX
20282  *
20283  * --------------------------------------------------------------*/
20284 NK_API int
20285 nk_check_text(struct nk_context *ctx, const char *text, int len, int active)
20286 {
20287  struct nk_window *win;
20288  struct nk_panel *layout;
20289  const struct nk_input *in;
20290  const struct nk_style *style;
20291 
20292  struct nk_rect bounds;
20293  enum nk_widget_layout_states state;
20294 
20295  NK_ASSERT(ctx);
20296  NK_ASSERT(ctx->current);
20297  NK_ASSERT(ctx->current->layout);
20298  if (!ctx || !ctx->current || !ctx->current->layout)
20299  return active;
20300 
20301  win = ctx->current;
20302  style = &ctx->style;
20303  layout = win->layout;
20304 
20305  state = nk_widget(&bounds, ctx);
20306  if (!state) return active;
20307  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20308  nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &active,
20309  text, len, NK_TOGGLE_CHECK, &style->checkbox, in, style->font);
20310  return active;
20311 }
20312 NK_API unsigned int
20313 nk_check_flags_text(struct nk_context *ctx, const char *text, int len,
20314  unsigned int flags, unsigned int value)
20315 {
20316  int old_active;
20317  NK_ASSERT(ctx);
20318  NK_ASSERT(text);
20319  if (!ctx || !text) return flags;
20320  old_active = (int)((flags & value) & value);
20321  if (nk_check_text(ctx, text, len, old_active))
20322  flags |= value;
20323  else flags &= ~value;
20324  return flags;
20325 }
20326 NK_API int
20327 nk_checkbox_text(struct nk_context *ctx, const char *text, int len, int *active)
20328 {
20329  int old_val;
20330  NK_ASSERT(ctx);
20331  NK_ASSERT(text);
20332  NK_ASSERT(active);
20333  if (!ctx || !text || !active) return 0;
20334  old_val = *active;
20335  *active = nk_check_text(ctx, text, len, *active);
20336  return old_val != *active;
20337 }
20338 NK_API int
20339 nk_checkbox_flags_text(struct nk_context *ctx, const char *text, int len,
20340  unsigned int *flags, unsigned int value)
20341 {
20342  int active;
20343  NK_ASSERT(ctx);
20344  NK_ASSERT(text);
20345  NK_ASSERT(flags);
20346  if (!ctx || !text || !flags) return 0;
20347 
20348  active = (int)((*flags & value) & value);
20349  if (nk_checkbox_text(ctx, text, len, &active)) {
20350  if (active) *flags |= value;
20351  else *flags &= ~value;
20352  return 1;
20353  }
20354  return 0;
20355 }
20356 NK_API int nk_check_label(struct nk_context *ctx, const char *label, int active)
20357 {
20358  return nk_check_text(ctx, label, nk_strlen(label), active);
20359 }
20360 NK_API unsigned int nk_check_flags_label(struct nk_context *ctx, const char *label,
20361  unsigned int flags, unsigned int value)
20362 {
20363  return nk_check_flags_text(ctx, label, nk_strlen(label), flags, value);
20364 }
20365 NK_API int nk_checkbox_label(struct nk_context *ctx, const char *label, int *active)
20366 {
20367  return nk_checkbox_text(ctx, label, nk_strlen(label), active);
20368 }
20369 NK_API int nk_checkbox_flags_label(struct nk_context *ctx, const char *label,
20370  unsigned int *flags, unsigned int value)
20371 {
20372  return nk_checkbox_flags_text(ctx, label, nk_strlen(label), flags, value);
20373 }
20374 /*----------------------------------------------------------------
20375  *
20376  * OPTION
20377  *
20378  * --------------------------------------------------------------*/
20379 NK_API int
20380 nk_option_text(struct nk_context *ctx, const char *text, int len, int is_active)
20381 {
20382  struct nk_window *win;
20383  struct nk_panel *layout;
20384  const struct nk_input *in;
20385  const struct nk_style *style;
20386 
20387  struct nk_rect bounds;
20388  enum nk_widget_layout_states state;
20389 
20390  NK_ASSERT(ctx);
20391  NK_ASSERT(ctx->current);
20392  NK_ASSERT(ctx->current->layout);
20393  if (!ctx || !ctx->current || !ctx->current->layout)
20394  return is_active;
20395 
20396  win = ctx->current;
20397  style = &ctx->style;
20398  layout = win->layout;
20399 
20400  state = nk_widget(&bounds, ctx);
20401  if (!state) return (int)state;
20402  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20403  nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &is_active,
20404  text, len, NK_TOGGLE_OPTION, &style->option, in, style->font);
20405  return is_active;
20406 }
20407 NK_API int
20408 nk_radio_text(struct nk_context *ctx, const char *text, int len, int *active)
20409 {
20410  int old_value;
20411  NK_ASSERT(ctx);
20412  NK_ASSERT(text);
20413  NK_ASSERT(active);
20414  if (!ctx || !text || !active) return 0;
20415  old_value = *active;
20416  *active = nk_option_text(ctx, text, len, old_value);
20417  return old_value != *active;
20418 }
20419 NK_API int
20420 nk_option_label(struct nk_context *ctx, const char *label, int active)
20421 {
20422  return nk_option_text(ctx, label, nk_strlen(label), active);
20423 }
20424 NK_API int
20425 nk_radio_label(struct nk_context *ctx, const char *label, int *active)
20426 {
20427  return nk_radio_text(ctx, label, nk_strlen(label), active);
20428 }
20429 
20430 
20431 
20432 
20433 
20434 /* ===============================================================
20435  *
20436  * SELECTABLE
20437  *
20438  * ===============================================================*/
20439 NK_LIB void
20440 nk_draw_selectable(struct nk_command_buffer *out,
20441  nk_flags state, const struct nk_style_selectable *style, int active,
20442  const struct nk_rect *bounds,
20443  const struct nk_rect *icon, const struct nk_image *img, enum nk_symbol_type sym,
20444  const char *string, int len, nk_flags align, const struct nk_user_font *font)
20445 {
20446  const struct nk_style_item *background;
20447  struct nk_text text;
20448  text.padding = style->padding;
20449 
20450  /* select correct colors/images */
20451  if (!active) {
20452  if (state & NK_WIDGET_STATE_ACTIVED) {
20453  background = &style->pressed;
20454  text.text = style->text_pressed;
20455  } else if (state & NK_WIDGET_STATE_HOVER) {
20456  background = &style->hover;
20457  text.text = style->text_hover;
20458  } else {
20459  background = &style->normal;
20460  text.text = style->text_normal;
20461  }
20462  } else {
20463  if (state & NK_WIDGET_STATE_ACTIVED) {
20464  background = &style->pressed_active;
20465  text.text = style->text_pressed_active;
20466  } else if (state & NK_WIDGET_STATE_HOVER) {
20467  background = &style->hover_active;
20468  text.text = style->text_hover_active;
20469  } else {
20470  background = &style->normal_active;
20471  text.text = style->text_normal_active;
20472  }
20473  }
20474  /* draw selectable background and text */
20475  if (background->type == NK_STYLE_ITEM_IMAGE) {
20476  nk_draw_image(out, *bounds, &background->data.image, nk_white);
20477  text.background = nk_rgba(0,0,0,0);
20478  } else {
20479  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
20480  text.background = background->data.color;
20481  }
20482  if (icon) {
20483  if (img) nk_draw_image(out, *icon, img, nk_white);
20484  else nk_draw_symbol(out, sym, *icon, text.background, text.text, 1, font);
20485  }
20486  nk_widget_text(out, *bounds, string, len, &text, align, font);
20487 }
20488 NK_LIB int
20489 nk_do_selectable(nk_flags *state, struct nk_command_buffer *out,
20490  struct nk_rect bounds, const char *str, int len, nk_flags align, int *value,
20491  const struct nk_style_selectable *style, const struct nk_input *in,
20492  const struct nk_user_font *font)
20493 {
20494  int old_value;
20495  struct nk_rect touch;
20496 
20497  NK_ASSERT(state);
20498  NK_ASSERT(out);
20499  NK_ASSERT(str);
20500  NK_ASSERT(len);
20501  NK_ASSERT(value);
20502  NK_ASSERT(style);
20503  NK_ASSERT(font);
20504 
20505  if (!state || !out || !str || !len || !value || !style || !font) return 0;
20506  old_value = *value;
20507 
20508  /* remove padding */
20509  touch.x = bounds.x - style->touch_padding.x;
20510  touch.y = bounds.y - style->touch_padding.y;
20511  touch.w = bounds.w + style->touch_padding.x * 2;
20512  touch.h = bounds.h + style->touch_padding.y * 2;
20513 
20514  /* update button */
20515  if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT))
20516  *value = !(*value);
20517 
20518  /* draw selectable */
20519  if (style->draw_begin) style->draw_begin(out, style->userdata);
20520  nk_draw_selectable(out, *state, style, *value, &bounds, 0,0,NK_SYMBOL_NONE, str, len, align, font);
20521  if (style->draw_end) style->draw_end(out, style->userdata);
20522  return old_value != *value;
20523 }
20524 NK_LIB int
20525 nk_do_selectable_image(nk_flags *state, struct nk_command_buffer *out,
20526  struct nk_rect bounds, const char *str, int len, nk_flags align, int *value,
20527  const struct nk_image *img, const struct nk_style_selectable *style,
20528  const struct nk_input *in, const struct nk_user_font *font)
20529 {
20530  int old_value;
20531  struct nk_rect touch;
20532  struct nk_rect icon;
20533 
20534  NK_ASSERT(state);
20535  NK_ASSERT(out);
20536  NK_ASSERT(str);
20537  NK_ASSERT(len);
20538  NK_ASSERT(value);
20539  NK_ASSERT(style);
20540  NK_ASSERT(font);
20541 
20542  if (!state || !out || !str || !len || !value || !style || !font) return 0;
20543  old_value = *value;
20544 
20545  /* toggle behavior */
20546  touch.x = bounds.x - style->touch_padding.x;
20547  touch.y = bounds.y - style->touch_padding.y;
20548  touch.w = bounds.w + style->touch_padding.x * 2;
20549  touch.h = bounds.h + style->touch_padding.y * 2;
20550  if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT))
20551  *value = !(*value);
20552 
20553  icon.y = bounds.y + style->padding.y;
20554  icon.w = icon.h = bounds.h - 2 * style->padding.y;
20555  if (align & NK_TEXT_ALIGN_LEFT) {
20556  icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w);
20557  icon.x = NK_MAX(icon.x, 0);
20558  } else icon.x = bounds.x + 2 * style->padding.x;
20559 
20560  icon.x += style->image_padding.x;
20561  icon.y += style->image_padding.y;
20562  icon.w -= 2 * style->image_padding.x;
20563  icon.h -= 2 * style->image_padding.y;
20564 
20565  /* draw selectable */
20566  if (style->draw_begin) style->draw_begin(out, style->userdata);
20567  nk_draw_selectable(out, *state, style, *value, &bounds, &icon, img, NK_SYMBOL_NONE, str, len, align, font);
20568  if (style->draw_end) style->draw_end(out, style->userdata);
20569  return old_value != *value;
20570 }
20571 NK_LIB int
20572 nk_do_selectable_symbol(nk_flags *state, struct nk_command_buffer *out,
20573  struct nk_rect bounds, const char *str, int len, nk_flags align, int *value,
20574  enum nk_symbol_type sym, const struct nk_style_selectable *style,
20575  const struct nk_input *in, const struct nk_user_font *font)
20576 {
20577  int old_value;
20578  struct nk_rect touch;
20579  struct nk_rect icon;
20580 
20581  NK_ASSERT(state);
20582  NK_ASSERT(out);
20583  NK_ASSERT(str);
20584  NK_ASSERT(len);
20585  NK_ASSERT(value);
20586  NK_ASSERT(style);
20587  NK_ASSERT(font);
20588 
20589  if (!state || !out || !str || !len || !value || !style || !font) return 0;
20590  old_value = *value;
20591 
20592  /* toggle behavior */
20593  touch.x = bounds.x - style->touch_padding.x;
20594  touch.y = bounds.y - style->touch_padding.y;
20595  touch.w = bounds.w + style->touch_padding.x * 2;
20596  touch.h = bounds.h + style->touch_padding.y * 2;
20597  if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT))
20598  *value = !(*value);
20599 
20600  icon.y = bounds.y + style->padding.y;
20601  icon.w = icon.h = bounds.h - 2 * style->padding.y;
20602  if (align & NK_TEXT_ALIGN_LEFT) {
20603  icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w);
20604  icon.x = NK_MAX(icon.x, 0);
20605  } else icon.x = bounds.x + 2 * style->padding.x;
20606 
20607  icon.x += style->image_padding.x;
20608  icon.y += style->image_padding.y;
20609  icon.w -= 2 * style->image_padding.x;
20610  icon.h -= 2 * style->image_padding.y;
20611 
20612  /* draw selectable */
20613  if (style->draw_begin) style->draw_begin(out, style->userdata);
20614  nk_draw_selectable(out, *state, style, *value, &bounds, &icon, 0, sym, str, len, align, font);
20615  if (style->draw_end) style->draw_end(out, style->userdata);
20616  return old_value != *value;
20617 }
20618 
20619 NK_API int
20620 nk_selectable_text(struct nk_context *ctx, const char *str, int len,
20621  nk_flags align, int *value)
20622 {
20623  struct nk_window *win;
20624  struct nk_panel *layout;
20625  const struct nk_input *in;
20626  const struct nk_style *style;
20627 
20628  enum nk_widget_layout_states state;
20629  struct nk_rect bounds;
20630 
20631  NK_ASSERT(ctx);
20632  NK_ASSERT(value);
20633  NK_ASSERT(ctx->current);
20634  NK_ASSERT(ctx->current->layout);
20635  if (!ctx || !ctx->current || !ctx->current->layout || !value)
20636  return 0;
20637 
20638  win = ctx->current;
20639  layout = win->layout;
20640  style = &ctx->style;
20641 
20642  state = nk_widget(&bounds, ctx);
20643  if (!state) return 0;
20644  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20645  return nk_do_selectable(&ctx->last_widget_state, &win->buffer, bounds,
20646  str, len, align, value, &style->selectable, in, style->font);
20647 }
20648 NK_API int
20649 nk_selectable_image_text(struct nk_context *ctx, struct nk_image img,
20650  const char *str, int len, nk_flags align, int *value)
20651 {
20652  struct nk_window *win;
20653  struct nk_panel *layout;
20654  const struct nk_input *in;
20655  const struct nk_style *style;
20656 
20657  enum nk_widget_layout_states state;
20658  struct nk_rect bounds;
20659 
20660  NK_ASSERT(ctx);
20661  NK_ASSERT(value);
20662  NK_ASSERT(ctx->current);
20663  NK_ASSERT(ctx->current->layout);
20664  if (!ctx || !ctx->current || !ctx->current->layout || !value)
20665  return 0;
20666 
20667  win = ctx->current;
20668  layout = win->layout;
20669  style = &ctx->style;
20670 
20671  state = nk_widget(&bounds, ctx);
20672  if (!state) return 0;
20673  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20674  return nk_do_selectable_image(&ctx->last_widget_state, &win->buffer, bounds,
20675  str, len, align, value, &img, &style->selectable, in, style->font);
20676 }
20677 NK_API int
20679  const char *str, int len, nk_flags align, int *value)
20680 {
20681  struct nk_window *win;
20682  struct nk_panel *layout;
20683  const struct nk_input *in;
20684  const struct nk_style *style;
20685 
20686  enum nk_widget_layout_states state;
20687  struct nk_rect bounds;
20688 
20689  NK_ASSERT(ctx);
20690  NK_ASSERT(value);
20691  NK_ASSERT(ctx->current);
20692  NK_ASSERT(ctx->current->layout);
20693  if (!ctx || !ctx->current || !ctx->current->layout || !value)
20694  return 0;
20695 
20696  win = ctx->current;
20697  layout = win->layout;
20698  style = &ctx->style;
20699 
20700  state = nk_widget(&bounds, ctx);
20701  if (!state) return 0;
20702  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20703  return nk_do_selectable_symbol(&ctx->last_widget_state, &win->buffer, bounds,
20704  str, len, align, value, sym, &style->selectable, in, style->font);
20705 }
20706 NK_API int
20708  const char *title, nk_flags align, int *value)
20709 {
20710  return nk_selectable_symbol_text(ctx, sym, title, nk_strlen(title), align, value);
20711 }
20712 NK_API int nk_select_text(struct nk_context *ctx, const char *str, int len,
20713  nk_flags align, int value)
20714 {
20715  nk_selectable_text(ctx, str, len, align, &value);return value;
20716 }
20717 NK_API int nk_selectable_label(struct nk_context *ctx, const char *str, nk_flags align, int *value)
20718 {
20719  return nk_selectable_text(ctx, str, nk_strlen(str), align, value);
20720 }
20721 NK_API int nk_selectable_image_label(struct nk_context *ctx,struct nk_image img,
20722  const char *str, nk_flags align, int *value)
20723 {
20724  return nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, value);
20725 }
20726 NK_API int nk_select_label(struct nk_context *ctx, const char *str, nk_flags align, int value)
20727 {
20728  nk_selectable_text(ctx, str, nk_strlen(str), align, &value);return value;
20729 }
20730 NK_API int nk_select_image_label(struct nk_context *ctx, struct nk_image img,
20731  const char *str, nk_flags align, int value)
20732 {
20733  nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, &value);return value;
20734 }
20735 NK_API int nk_select_image_text(struct nk_context *ctx, struct nk_image img,
20736  const char *str, int len, nk_flags align, int value)
20737 {
20738  nk_selectable_image_text(ctx, img, str, len, align, &value);return value;
20739 }
20740 NK_API int
20741 nk_select_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
20742  const char *title, int title_len, nk_flags align, int value)
20743 {
20744  nk_selectable_symbol_text(ctx, sym, title, title_len, align, &value);return value;
20745 }
20746 NK_API int
20747 nk_select_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym,
20748  const char *title, nk_flags align, int value)
20749 {
20750  return nk_select_symbol_text(ctx, sym, title, nk_strlen(title), align, value);
20751 }
20752 
20753 
20754 
20755 
20756 
20757 /* ===============================================================
20758  *
20759  * SLIDER
20760  *
20761  * ===============================================================*/
20762 NK_LIB float
20763 nk_slider_behavior(nk_flags *state, struct nk_rect *logical_cursor,
20764  struct nk_rect *visual_cursor, struct nk_input *in,
20765  struct nk_rect bounds, float slider_min, float slider_max, float slider_value,
20766  float slider_step, float slider_steps)
20767 {
20768  int left_mouse_down;
20769  int left_mouse_click_in_cursor;
20770 
20771  /* check if visual cursor is being dragged */
20772  nk_widget_state_reset(state);
20773  left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
20774  left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in,
20775  NK_BUTTON_LEFT, *visual_cursor, nk_true);
20776 
20777  if (left_mouse_down && left_mouse_click_in_cursor) {
20778  float ratio = 0;
20779  const float d = in->mouse.pos.x - (visual_cursor->x+visual_cursor->w*0.5f);
20780  const float pxstep = bounds.w / slider_steps;
20781 
20782  /* only update value if the next slider step is reached */
20783  *state = NK_WIDGET_STATE_ACTIVE;
20784  if (NK_ABS(d) >= pxstep) {
20785  const float steps = (float)((int)(NK_ABS(d) / pxstep));
20786  slider_value += (d > 0) ? (slider_step*steps) : -(slider_step*steps);
20787  slider_value = NK_CLAMP(slider_min, slider_value, slider_max);
20788  ratio = (slider_value - slider_min)/slider_step;
20789  logical_cursor->x = bounds.x + (logical_cursor->w * ratio);
20790  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = logical_cursor->x;
20791  }
20792  }
20793 
20794  /* slider widget state */
20795  if (nk_input_is_mouse_hovering_rect(in, bounds))
20796  *state = NK_WIDGET_STATE_HOVERED;
20797  if (*state & NK_WIDGET_STATE_HOVER &&
20799  *state |= NK_WIDGET_STATE_ENTERED;
20800  else if (nk_input_is_mouse_prev_hovering_rect(in, bounds))
20801  *state |= NK_WIDGET_STATE_LEFT;
20802  return slider_value;
20803 }
20804 NK_LIB void
20805 nk_draw_slider(struct nk_command_buffer *out, nk_flags state,
20806  const struct nk_style_slider *style, const struct nk_rect *bounds,
20807  const struct nk_rect *visual_cursor, float min, float value, float max)
20808 {
20809  struct nk_rect fill;
20810  struct nk_rect bar;
20811  const struct nk_style_item *background;
20812 
20813  /* select correct slider images/colors */
20814  struct nk_color bar_color;
20815  const struct nk_style_item *cursor;
20816 
20817  NK_UNUSED(min);
20818  NK_UNUSED(max);
20819  NK_UNUSED(value);
20820 
20821  if (state & NK_WIDGET_STATE_ACTIVED) {
20822  background = &style->active;
20823  bar_color = style->bar_active;
20824  cursor = &style->cursor_active;
20825  } else if (state & NK_WIDGET_STATE_HOVER) {
20826  background = &style->hover;
20827  bar_color = style->bar_hover;
20828  cursor = &style->cursor_hover;
20829  } else {
20830  background = &style->normal;
20831  bar_color = style->bar_normal;
20832  cursor = &style->cursor_normal;
20833  }
20834  /* calculate slider background bar */
20835  bar.x = bounds->x;
20836  bar.y = (visual_cursor->y + visual_cursor->h/2) - bounds->h/12;
20837  bar.w = bounds->w;
20838  bar.h = bounds->h/6;
20839 
20840  /* filled background bar style */
20841  fill.w = (visual_cursor->x + (visual_cursor->w/2.0f)) - bar.x;
20842  fill.x = bar.x;
20843  fill.y = bar.y;
20844  fill.h = bar.h;
20845 
20846  /* draw background */
20847  if (background->type == NK_STYLE_ITEM_IMAGE) {
20848  nk_draw_image(out, *bounds, &background->data.image, nk_white);
20849  } else {
20850  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
20851  nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
20852  }
20853 
20854  /* draw slider bar */
20855  nk_fill_rect(out, bar, style->rounding, bar_color);
20856  nk_fill_rect(out, fill, style->rounding, style->bar_filled);
20857 
20858  /* draw cursor */
20859  if (cursor->type == NK_STYLE_ITEM_IMAGE)
20860  nk_draw_image(out, *visual_cursor, &cursor->data.image, nk_white);
20861  else nk_fill_circle(out, *visual_cursor, cursor->data.color);
20862 }
20863 NK_LIB float
20864 nk_do_slider(nk_flags *state,
20865  struct nk_command_buffer *out, struct nk_rect bounds,
20866  float min, float val, float max, float step,
20867  const struct nk_style_slider *style, struct nk_input *in,
20868  const struct nk_user_font *font)
20869 {
20870  float slider_range;
20871  float slider_min;
20872  float slider_max;
20873  float slider_value;
20874  float slider_steps;
20875  float cursor_offset;
20876 
20877  struct nk_rect visual_cursor;
20878  struct nk_rect logical_cursor;
20879 
20880  NK_ASSERT(style);
20881  NK_ASSERT(out);
20882  if (!out || !style)
20883  return 0;
20884 
20885  /* remove padding from slider bounds */
20886  bounds.x = bounds.x + style->padding.x;
20887  bounds.y = bounds.y + style->padding.y;
20888  bounds.h = NK_MAX(bounds.h, 2*style->padding.y);
20889  bounds.w = NK_MAX(bounds.w, 2*style->padding.x + style->cursor_size.x);
20890  bounds.w -= 2 * style->padding.x;
20891  bounds.h -= 2 * style->padding.y;
20892 
20893  /* optional buttons */
20894  if (style->show_buttons) {
20895  nk_flags ws;
20896  struct nk_rect button;
20897  button.y = bounds.y;
20898  button.w = bounds.h;
20899  button.h = bounds.h;
20900 
20901  /* decrement button */
20902  button.x = bounds.x;
20903  if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, NK_BUTTON_DEFAULT,
20904  &style->dec_button, in, font))
20905  val -= step;
20906 
20907  /* increment button */
20908  button.x = (bounds.x + bounds.w) - button.w;
20909  if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, NK_BUTTON_DEFAULT,
20910  &style->inc_button, in, font))
20911  val += step;
20912 
20913  bounds.x = bounds.x + button.w + style->spacing.x;
20914  bounds.w = bounds.w - (2*button.w + 2*style->spacing.x);
20915  }
20916 
20917  /* remove one cursor size to support visual cursor */
20918  bounds.x += style->cursor_size.x*0.5f;
20919  bounds.w -= style->cursor_size.x;
20920 
20921  /* make sure the provided values are correct */
20922  slider_max = NK_MAX(min, max);
20923  slider_min = NK_MIN(min, max);
20924  slider_value = NK_CLAMP(slider_min, val, slider_max);
20925  slider_range = slider_max - slider_min;
20926  slider_steps = slider_range / step;
20927  cursor_offset = (slider_value - slider_min) / step;
20928 
20929  /* calculate cursor
20930  Basically you have two cursors. One for visual representation and interaction
20931  and one for updating the actual cursor value. */
20932  logical_cursor.h = bounds.h;
20933  logical_cursor.w = bounds.w / slider_steps;
20934  logical_cursor.x = bounds.x + (logical_cursor.w * cursor_offset);
20935  logical_cursor.y = bounds.y;
20936 
20937  visual_cursor.h = style->cursor_size.y;
20938  visual_cursor.w = style->cursor_size.x;
20939  visual_cursor.y = (bounds.y + bounds.h*0.5f) - visual_cursor.h*0.5f;
20940  visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f;
20941 
20942  slider_value = nk_slider_behavior(state, &logical_cursor, &visual_cursor,
20943  in, bounds, slider_min, slider_max, slider_value, step, slider_steps);
20944  visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f;
20945 
20946  /* draw slider */
20947  if (style->draw_begin) style->draw_begin(out, style->userdata);
20948  nk_draw_slider(out, *state, style, &bounds, &visual_cursor, slider_min, slider_value, slider_max);
20949  if (style->draw_end) style->draw_end(out, style->userdata);
20950  return slider_value;
20951 }
20952 NK_API int
20953 nk_slider_float(struct nk_context *ctx, float min_value, float *value, float max_value,
20954  float value_step)
20955 {
20956  struct nk_window *win;
20957  struct nk_panel *layout;
20958  struct nk_input *in;
20959  const struct nk_style *style;
20960 
20961  int ret = 0;
20962  float old_value;
20963  struct nk_rect bounds;
20964  enum nk_widget_layout_states state;
20965 
20966  NK_ASSERT(ctx);
20967  NK_ASSERT(ctx->current);
20968  NK_ASSERT(ctx->current->layout);
20969  NK_ASSERT(value);
20970  if (!ctx || !ctx->current || !ctx->current->layout || !value)
20971  return ret;
20972 
20973  win = ctx->current;
20974  style = &ctx->style;
20975  layout = win->layout;
20976 
20977  state = nk_widget(&bounds, ctx);
20978  if (!state) return ret;
20979  in = (/*state == NK_WIDGET_ROM || */ layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20980 
20981  old_value = *value;
20982  *value = nk_do_slider(&ctx->last_widget_state, &win->buffer, bounds, min_value,
20983  old_value, max_value, value_step, &style->slider, in, style->font);
20984  return (old_value > *value || old_value < *value);
20985 }
20986 NK_API float
20987 nk_slide_float(struct nk_context *ctx, float min, float val, float max, float step)
20988 {
20989  nk_slider_float(ctx, min, &val, max, step); return val;
20990 }
20991 NK_API int
20992 nk_slide_int(struct nk_context *ctx, int min, int val, int max, int step)
20993 {
20994  float value = (float)val;
20995  nk_slider_float(ctx, (float)min, &value, (float)max, (float)step);
20996  return (int)value;
20997 }
20998 NK_API int
20999 nk_slider_int(struct nk_context *ctx, int min, int *val, int max, int step)
21000 {
21001  int ret;
21002  float value = (float)*val;
21003  ret = nk_slider_float(ctx, (float)min, &value, (float)max, (float)step);
21004  *val = (int)value;
21005  return ret;
21006 }
21007 
21008 
21009 
21010 
21011 
21012 /* ===============================================================
21013  *
21014  * PROGRESS
21015  *
21016  * ===============================================================*/
21018 nk_progress_behavior(nk_flags *state, struct nk_input *in,
21019  struct nk_rect r, struct nk_rect cursor, nk_size max, nk_size value, int modifiable)
21020 {
21021  int left_mouse_down = 0;
21022  int left_mouse_click_in_cursor = 0;
21023 
21024  nk_widget_state_reset(state);
21025  if (!in || !modifiable) return value;
21026  left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
21027  left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in,
21028  NK_BUTTON_LEFT, cursor, nk_true);
21030  *state = NK_WIDGET_STATE_HOVERED;
21031 
21032  if (in && left_mouse_down && left_mouse_click_in_cursor) {
21033  if (left_mouse_down && left_mouse_click_in_cursor) {
21034  float ratio = NK_MAX(0, (float)(in->mouse.pos.x - cursor.x)) / (float)cursor.w;
21035  value = (nk_size)NK_CLAMP(0, (float)max * ratio, (float)max);
21036  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor.x + cursor.w/2.0f;
21037  *state |= NK_WIDGET_STATE_ACTIVE;
21038  }
21039  }
21040  /* set progressbar widget state */
21042  *state |= NK_WIDGET_STATE_ENTERED;
21043  else if (nk_input_is_mouse_prev_hovering_rect(in, r))
21044  *state |= NK_WIDGET_STATE_LEFT;
21045  return value;
21046 }
21047 NK_LIB void
21048 nk_draw_progress(struct nk_command_buffer *out, nk_flags state,
21049  const struct nk_style_progress *style, const struct nk_rect *bounds,
21050  const struct nk_rect *scursor, nk_size value, nk_size max)
21051 {
21052  const struct nk_style_item *background;
21053  const struct nk_style_item *cursor;
21054 
21055  NK_UNUSED(max);
21056  NK_UNUSED(value);
21057 
21058  /* select correct colors/images to draw */
21059  if (state & NK_WIDGET_STATE_ACTIVED) {
21060  background = &style->active;
21061  cursor = &style->cursor_active;
21062  } else if (state & NK_WIDGET_STATE_HOVER){
21063  background = &style->hover;
21064  cursor = &style->cursor_hover;
21065  } else {
21066  background = &style->normal;
21067  cursor = &style->cursor_normal;
21068  }
21069 
21070  /* draw background */
21071  if (background->type == NK_STYLE_ITEM_COLOR) {
21072  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
21073  nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
21074  } else nk_draw_image(out, *bounds, &background->data.image, nk_white);
21075 
21076  /* draw cursor */
21077  if (cursor->type == NK_STYLE_ITEM_COLOR) {
21078  nk_fill_rect(out, *scursor, style->rounding, cursor->data.color);
21079  nk_stroke_rect(out, *scursor, style->rounding, style->border, style->border_color);
21080  } else nk_draw_image(out, *scursor, &cursor->data.image, nk_white);
21081 }
21083 nk_do_progress(nk_flags *state,
21084  struct nk_command_buffer *out, struct nk_rect bounds,
21085  nk_size value, nk_size max, int modifiable,
21086  const struct nk_style_progress *style, struct nk_input *in)
21087 {
21088  float prog_scale;
21089  nk_size prog_value;
21090  struct nk_rect cursor;
21091 
21092  NK_ASSERT(style);
21093  NK_ASSERT(out);
21094  if (!out || !style) return 0;
21095 
21096  /* calculate progressbar cursor */
21097  cursor.w = NK_MAX(bounds.w, 2 * style->padding.x + 2 * style->border);
21098  cursor.h = NK_MAX(bounds.h, 2 * style->padding.y + 2 * style->border);
21099  cursor = nk_pad_rect(bounds, nk_vec2(style->padding.x + style->border, style->padding.y + style->border));
21100  prog_scale = (float)value / (float)max;
21101 
21102  /* update progressbar */
21103  prog_value = NK_MIN(value, max);
21104  prog_value = nk_progress_behavior(state, in, bounds, cursor,max, prog_value, modifiable);
21105  cursor.w = cursor.w * prog_scale;
21106 
21107  /* draw progressbar */
21108  if (style->draw_begin) style->draw_begin(out, style->userdata);
21109  nk_draw_progress(out, *state, style, &bounds, &cursor, value, max);
21110  if (style->draw_end) style->draw_end(out, style->userdata);
21111  return prog_value;
21112 }
21113 NK_API int
21114 nk_progress(struct nk_context *ctx, nk_size *cur, nk_size max, int is_modifyable)
21115 {
21116  struct nk_window *win;
21117  struct nk_panel *layout;
21118  const struct nk_style *style;
21119  struct nk_input *in;
21120 
21121  struct nk_rect bounds;
21122  enum nk_widget_layout_states state;
21123  nk_size old_value;
21124 
21125  NK_ASSERT(ctx);
21126  NK_ASSERT(cur);
21127  NK_ASSERT(ctx->current);
21128  NK_ASSERT(ctx->current->layout);
21129  if (!ctx || !ctx->current || !ctx->current->layout || !cur)
21130  return 0;
21131 
21132  win = ctx->current;
21133  style = &ctx->style;
21134  layout = win->layout;
21135  state = nk_widget(&bounds, ctx);
21136  if (!state) return 0;
21137 
21138  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
21139  old_value = *cur;
21140  *cur = nk_do_progress(&ctx->last_widget_state, &win->buffer, bounds,
21141  *cur, max, is_modifyable, &style->progress, in);
21142  return (*cur != old_value);
21143 }
21145 nk_prog(struct nk_context *ctx, nk_size cur, nk_size max, int modifyable)
21146 {
21147  nk_progress(ctx, &cur, max, modifyable);
21148  return cur;
21149 }
21150 
21151 
21152 
21153 
21154 
21155 /* ===============================================================
21156  *
21157  * SCROLLBAR
21158  *
21159  * ===============================================================*/
21160 NK_LIB float
21161 nk_scrollbar_behavior(nk_flags *state, struct nk_input *in,
21162  int has_scrolling, const struct nk_rect *scroll,
21163  const struct nk_rect *cursor, const struct nk_rect *empty0,
21164  const struct nk_rect *empty1, float scroll_offset,
21165  float target, float scroll_step, enum nk_orientation o)
21166 {
21167  nk_flags ws = 0;
21168  int left_mouse_down;
21169  int left_mouse_click_in_cursor;
21170  float scroll_delta;
21171 
21172  nk_widget_state_reset(state);
21173  if (!in) return scroll_offset;
21174 
21175  left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
21176  left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
21177  NK_BUTTON_LEFT, *cursor, nk_true);
21178  if (nk_input_is_mouse_hovering_rect(in, *scroll))
21179  *state = NK_WIDGET_STATE_HOVERED;
21180 
21181  scroll_delta = (o == NK_VERTICAL) ? in->mouse.scroll_delta.y: in->mouse.scroll_delta.x;
21182  if (left_mouse_down && left_mouse_click_in_cursor) {
21183  /* update cursor by mouse dragging */
21184  float pixel, delta;
21185  *state = NK_WIDGET_STATE_ACTIVE;
21186  if (o == NK_VERTICAL) {
21187  float cursor_y;
21188  pixel = in->mouse.delta.y;
21189  delta = (pixel / scroll->h) * target;
21190  scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->h);
21191  cursor_y = scroll->y + ((scroll_offset/target) * scroll->h);
21192  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = cursor_y + cursor->h/2.0f;
21193  } else {
21194  float cursor_x;
21195  pixel = in->mouse.delta.x;
21196  delta = (pixel / scroll->w) * target;
21197  scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->w);
21198  cursor_x = scroll->x + ((scroll_offset/target) * scroll->w);
21199  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor_x + cursor->w/2.0f;
21200  }
21201  } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_UP) && o == NK_VERTICAL && has_scrolling)||
21202  nk_button_behavior(&ws, *empty0, in, NK_BUTTON_DEFAULT)) {
21203  /* scroll page up by click on empty space or shortcut */
21204  if (o == NK_VERTICAL)
21205  scroll_offset = NK_MAX(0, scroll_offset - scroll->h);
21206  else scroll_offset = NK_MAX(0, scroll_offset - scroll->w);
21207  } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_DOWN) && o == NK_VERTICAL && has_scrolling) ||
21208  nk_button_behavior(&ws, *empty1, in, NK_BUTTON_DEFAULT)) {
21209  /* scroll page down by click on empty space or shortcut */
21210  if (o == NK_VERTICAL)
21211  scroll_offset = NK_MIN(scroll_offset + scroll->h, target - scroll->h);
21212  else scroll_offset = NK_MIN(scroll_offset + scroll->w, target - scroll->w);
21213  } else if (has_scrolling) {
21214  if ((scroll_delta < 0 || (scroll_delta > 0))) {
21215  /* update cursor by mouse scrolling */
21216  scroll_offset = scroll_offset + scroll_step * (-scroll_delta);
21217  if (o == NK_VERTICAL)
21218  scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->h);
21219  else scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->w);
21220  } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_START)) {
21221  /* update cursor to the beginning */
21222  if (o == NK_VERTICAL) scroll_offset = 0;
21223  } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_END)) {
21224  /* update cursor to the end */
21225  if (o == NK_VERTICAL) scroll_offset = target - scroll->h;
21226  }
21227  }
21228  if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *scroll))
21229  *state |= NK_WIDGET_STATE_ENTERED;
21230  else if (nk_input_is_mouse_prev_hovering_rect(in, *scroll))
21231  *state |= NK_WIDGET_STATE_LEFT;
21232  return scroll_offset;
21233 }
21234 NK_LIB void
21235 nk_draw_scrollbar(struct nk_command_buffer *out, nk_flags state,
21236  const struct nk_style_scrollbar *style, const struct nk_rect *bounds,
21237  const struct nk_rect *scroll)
21238 {
21239  const struct nk_style_item *background;
21240  const struct nk_style_item *cursor;
21241 
21242  /* select correct colors/images to draw */
21243  if (state & NK_WIDGET_STATE_ACTIVED) {
21244  background = &style->active;
21245  cursor = &style->cursor_active;
21246  } else if (state & NK_WIDGET_STATE_HOVER) {
21247  background = &style->hover;
21248  cursor = &style->cursor_hover;
21249  } else {
21250  background = &style->normal;
21251  cursor = &style->cursor_normal;
21252  }
21253 
21254  /* draw background */
21255  if (background->type == NK_STYLE_ITEM_COLOR) {
21256  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
21257  nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
21258  } else {
21259  nk_draw_image(out, *bounds, &background->data.image, nk_white);
21260  }
21261 
21262  /* draw cursor */
21263  if (background->type == NK_STYLE_ITEM_COLOR) {
21264  nk_fill_rect(out, *scroll, style->rounding_cursor, cursor->data.color);
21265  nk_stroke_rect(out, *scroll, style->rounding_cursor, style->border_cursor, style->cursor_border_color);
21266  } else nk_draw_image(out, *scroll, &cursor->data.image, nk_white);
21267 }
21268 NK_LIB float
21269 nk_do_scrollbarv(nk_flags *state,
21270  struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling,
21271  float offset, float target, float step, float button_pixel_inc,
21272  const struct nk_style_scrollbar *style, struct nk_input *in,
21273  const struct nk_user_font *font)
21274 {
21275  struct nk_rect empty_north;
21276  struct nk_rect empty_south;
21277  struct nk_rect cursor;
21278 
21279  float scroll_step;
21280  float scroll_offset;
21281  float scroll_off;
21282  float scroll_ratio;
21283 
21284  NK_ASSERT(out);
21285  NK_ASSERT(style);
21286  NK_ASSERT(state);
21287  if (!out || !style) return 0;
21288 
21289  scroll.w = NK_MAX(scroll.w, 1);
21290  scroll.h = NK_MAX(scroll.h, 0);
21291  if (target <= scroll.h) return 0;
21292 
21293  /* optional scrollbar buttons */
21294  if (style->show_buttons) {
21295  nk_flags ws;
21296  float scroll_h;
21297  struct nk_rect button;
21298 
21299  button.x = scroll.x;
21300  button.w = scroll.w;
21301  button.h = scroll.w;
21302 
21303  scroll_h = NK_MAX(scroll.h - 2 * button.h,0);
21304  scroll_step = NK_MIN(step, button_pixel_inc);
21305 
21306  /* decrement button */
21307  button.y = scroll.y;
21308  if (nk_do_button_symbol(&ws, out, button, style->dec_symbol,
21309  NK_BUTTON_REPEATER, &style->dec_button, in, font))
21310  offset = offset - scroll_step;
21311 
21312  /* increment button */
21313  button.y = scroll.y + scroll.h - button.h;
21314  if (nk_do_button_symbol(&ws, out, button, style->inc_symbol,
21315  NK_BUTTON_REPEATER, &style->inc_button, in, font))
21316  offset = offset + scroll_step;
21317 
21318  scroll.y = scroll.y + button.h;
21319  scroll.h = scroll_h;
21320  }
21321 
21322  /* calculate scrollbar constants */
21323  scroll_step = NK_MIN(step, scroll.h);
21324  scroll_offset = NK_CLAMP(0, offset, target - scroll.h);
21325  scroll_ratio = scroll.h / target;
21326  scroll_off = scroll_offset / target;
21327 
21328  /* calculate scrollbar cursor bounds */
21329  cursor.h = NK_MAX((scroll_ratio * scroll.h) - (2*style->border + 2*style->padding.y), 0);
21330  cursor.y = scroll.y + (scroll_off * scroll.h) + style->border + style->padding.y;
21331  cursor.w = scroll.w - (2 * style->border + 2 * style->padding.x);
21332  cursor.x = scroll.x + style->border + style->padding.x;
21333 
21334  /* calculate empty space around cursor */
21335  empty_north.x = scroll.x;
21336  empty_north.y = scroll.y;
21337  empty_north.w = scroll.w;
21338  empty_north.h = NK_MAX(cursor.y - scroll.y, 0);
21339 
21340  empty_south.x = scroll.x;
21341  empty_south.y = cursor.y + cursor.h;
21342  empty_south.w = scroll.w;
21343  empty_south.h = NK_MAX((scroll.y + scroll.h) - (cursor.y + cursor.h), 0);
21344 
21345  /* update scrollbar */
21346  scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor,
21347  &empty_north, &empty_south, scroll_offset, target, scroll_step, NK_VERTICAL);
21348  scroll_off = scroll_offset / target;
21349  cursor.y = scroll.y + (scroll_off * scroll.h) + style->border_cursor + style->padding.y;
21350 
21351  /* draw scrollbar */
21352  if (style->draw_begin) style->draw_begin(out, style->userdata);
21353  nk_draw_scrollbar(out, *state, style, &scroll, &cursor);
21354  if (style->draw_end) style->draw_end(out, style->userdata);
21355  return scroll_offset;
21356 }
21357 NK_LIB float
21358 nk_do_scrollbarh(nk_flags *state,
21359  struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling,
21360  float offset, float target, float step, float button_pixel_inc,
21361  const struct nk_style_scrollbar *style, struct nk_input *in,
21362  const struct nk_user_font *font)
21363 {
21364  struct nk_rect cursor;
21365  struct nk_rect empty_west;
21366  struct nk_rect empty_east;
21367 
21368  float scroll_step;
21369  float scroll_offset;
21370  float scroll_off;
21371  float scroll_ratio;
21372 
21373  NK_ASSERT(out);
21374  NK_ASSERT(style);
21375  if (!out || !style) return 0;
21376 
21377  /* scrollbar background */
21378  scroll.h = NK_MAX(scroll.h, 1);
21379  scroll.w = NK_MAX(scroll.w, 2 * scroll.h);
21380  if (target <= scroll.w) return 0;
21381 
21382  /* optional scrollbar buttons */
21383  if (style->show_buttons) {
21384  nk_flags ws;
21385  float scroll_w;
21386  struct nk_rect button;
21387  button.y = scroll.y;
21388  button.w = scroll.h;
21389  button.h = scroll.h;
21390 
21391  scroll_w = scroll.w - 2 * button.w;
21392  scroll_step = NK_MIN(step, button_pixel_inc);
21393 
21394  /* decrement button */
21395  button.x = scroll.x;
21396  if (nk_do_button_symbol(&ws, out, button, style->dec_symbol,
21397  NK_BUTTON_REPEATER, &style->dec_button, in, font))
21398  offset = offset - scroll_step;
21399 
21400  /* increment button */
21401  button.x = scroll.x + scroll.w - button.w;
21402  if (nk_do_button_symbol(&ws, out, button, style->inc_symbol,
21403  NK_BUTTON_REPEATER, &style->inc_button, in, font))
21404  offset = offset + scroll_step;
21405 
21406  scroll.x = scroll.x + button.w;
21407  scroll.w = scroll_w;
21408  }
21409 
21410  /* calculate scrollbar constants */
21411  scroll_step = NK_MIN(step, scroll.w);
21412  scroll_offset = NK_CLAMP(0, offset, target - scroll.w);
21413  scroll_ratio = scroll.w / target;
21414  scroll_off = scroll_offset / target;
21415 
21416  /* calculate cursor bounds */
21417  cursor.w = (scroll_ratio * scroll.w) - (2*style->border + 2*style->padding.x);
21418  cursor.x = scroll.x + (scroll_off * scroll.w) + style->border + style->padding.x;
21419  cursor.h = scroll.h - (2 * style->border + 2 * style->padding.y);
21420  cursor.y = scroll.y + style->border + style->padding.y;
21421 
21422  /* calculate empty space around cursor */
21423  empty_west.x = scroll.x;
21424  empty_west.y = scroll.y;
21425  empty_west.w = cursor.x - scroll.x;
21426  empty_west.h = scroll.h;
21427 
21428  empty_east.x = cursor.x + cursor.w;
21429  empty_east.y = scroll.y;
21430  empty_east.w = (scroll.x + scroll.w) - (cursor.x + cursor.w);
21431  empty_east.h = scroll.h;
21432 
21433  /* update scrollbar */
21434  scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor,
21435  &empty_west, &empty_east, scroll_offset, target, scroll_step, NK_HORIZONTAL);
21436  scroll_off = scroll_offset / target;
21437  cursor.x = scroll.x + (scroll_off * scroll.w);
21438 
21439  /* draw scrollbar */
21440  if (style->draw_begin) style->draw_begin(out, style->userdata);
21441  nk_draw_scrollbar(out, *state, style, &scroll, &cursor);
21442  if (style->draw_end) style->draw_end(out, style->userdata);
21443  return scroll_offset;
21444 }
21445 
21446 
21447 
21448 
21449 
21450 /* ===============================================================
21451  *
21452  * TEXT EDITOR
21453  *
21454  * ===============================================================*/
21455 /* stb_textedit.h - v1.8 - public domain - Sean Barrett */
21456 struct nk_text_find {
21457  float x,y; /* position of n'th character */
21458  float height; /* height of line */
21459  int first_char, length; /* first char of row, and length */
21460  int prev_first; /*_ first char of previous row */
21461 };
21462 
21463 struct nk_text_edit_row {
21464  float x0,x1;
21465  /* starting x location, end x location (allows for align=right, etc) */
21466  float baseline_y_delta;
21467  /* position of baseline relative to previous row's baseline*/
21468  float ymin,ymax;
21469  /* height of row above and below baseline */
21470  int num_chars;
21471 };
21472 
21473 /* forward declarations */
21474 NK_INTERN void nk_textedit_makeundo_delete(struct nk_text_edit*, int, int);
21475 NK_INTERN void nk_textedit_makeundo_insert(struct nk_text_edit*, int, int);
21476 NK_INTERN void nk_textedit_makeundo_replace(struct nk_text_edit*, int, int, int);
21477 #define NK_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end)
21478 
21479 NK_INTERN float
21480 nk_textedit_get_width(const struct nk_text_edit *edit, int line_start, int char_id,
21481  const struct nk_user_font *font)
21482 {
21483  int len = 0;
21484  nk_rune unicode = 0;
21485  const char *str = nk_str_at_const(&edit->string, line_start + char_id, &unicode, &len);
21486  return font->width(font->userdata, font->height, str, len);
21487 }
21488 NK_INTERN void
21489 nk_textedit_layout_row(struct nk_text_edit_row *r, struct nk_text_edit *edit,
21490  int line_start_id, float row_height, const struct nk_user_font *font)
21491 {
21492  int l;
21493  int glyphs = 0;
21494  nk_rune unicode;
21495  const char *remaining;
21496  int len = nk_str_len_char(&edit->string);
21497  const char *end = nk_str_get_const(&edit->string) + len;
21498  const char *text = nk_str_at_const(&edit->string, line_start_id, &unicode, &l);
21499  const struct nk_vec2 size = nk_text_calculate_text_bounds(font,
21500  text, (int)(end - text), row_height, &remaining, 0, &glyphs, NK_STOP_ON_NEW_LINE);
21501 
21502  r->x0 = 0.0f;
21503  r->x1 = size.x;
21504  r->baseline_y_delta = size.y;
21505  r->ymin = 0.0f;
21506  r->ymax = size.y;
21507  r->num_chars = glyphs;
21508 }
21509 NK_INTERN int
21510 nk_textedit_locate_coord(struct nk_text_edit *edit, float x, float y,
21511  const struct nk_user_font *font, float row_height)
21512 {
21513  struct nk_text_edit_row r;
21514  int n = edit->string.len;
21515  float base_y = 0, prev_x;
21516  int i=0, k;
21517 
21518  r.x0 = r.x1 = 0;
21519  r.ymin = r.ymax = 0;
21520  r.num_chars = 0;
21521 
21522  /* search rows to find one that straddles 'y' */
21523  while (i < n) {
21524  nk_textedit_layout_row(&r, edit, i, row_height, font);
21525  if (r.num_chars <= 0)
21526  return n;
21527 
21528  if (i==0 && y < base_y + r.ymin)
21529  return 0;
21530 
21531  if (y < base_y + r.ymax)
21532  break;
21533 
21534  i += r.num_chars;
21535  base_y += r.baseline_y_delta;
21536  }
21537 
21538  /* below all text, return 'after' last character */
21539  if (i >= n)
21540  return n;
21541 
21542  /* check if it's before the beginning of the line */
21543  if (x < r.x0)
21544  return i;
21545 
21546  /* check if it's before the end of the line */
21547  if (x < r.x1) {
21548  /* search characters in row for one that straddles 'x' */
21549  k = i;
21550  prev_x = r.x0;
21551  for (i=0; i < r.num_chars; ++i) {
21552  float w = nk_textedit_get_width(edit, k, i, font);
21553  if (x < prev_x+w) {
21554  if (x < prev_x+w/2)
21555  return k+i;
21556  else return k+i+1;
21557  }
21558  prev_x += w;
21559  }
21560  /* shouldn't happen, but if it does, fall through to end-of-line case */
21561  }
21562 
21563  /* if the last character is a newline, return that.
21564  * otherwise return 'after' the last character */
21565  if (nk_str_rune_at(&edit->string, i+r.num_chars-1) == '\n')
21566  return i+r.num_chars-1;
21567  else return i+r.num_chars;
21568 }
21569 NK_LIB void
21570 nk_textedit_click(struct nk_text_edit *state, float x, float y,
21571  const struct nk_user_font *font, float row_height)
21572 {
21573  /* API click: on mouse down, move the cursor to the clicked location,
21574  * and reset the selection */
21575  state->cursor = nk_textedit_locate_coord(state, x, y, font, row_height);
21576  state->select_start = state->cursor;
21577  state->select_end = state->cursor;
21578  state->has_preferred_x = 0;
21579 }
21580 NK_LIB void
21581 nk_textedit_drag(struct nk_text_edit *state, float x, float y,
21582  const struct nk_user_font *font, float row_height)
21583 {
21584  /* API drag: on mouse drag, move the cursor and selection endpoint
21585  * to the clicked location */
21586  int p = nk_textedit_locate_coord(state, x, y, font, row_height);
21587  if (state->select_start == state->select_end)
21588  state->select_start = state->cursor;
21589  state->cursor = state->select_end = p;
21590 }
21591 NK_INTERN void
21592 nk_textedit_find_charpos(struct nk_text_find *find, struct nk_text_edit *state,
21593  int n, int single_line, const struct nk_user_font *font, float row_height)
21594 {
21595  /* find the x/y location of a character, and remember info about the previous
21596  * row in case we get a move-up event (for page up, we'll have to rescan) */
21597  struct nk_text_edit_row r;
21598  int prev_start = 0;
21599  int z = state->string.len;
21600  int i=0, first;
21601 
21602  nk_zero_struct(r);
21603  if (n == z) {
21604  /* if it's at the end, then find the last line -- simpler than trying to
21605  explicitly handle this case in the regular code */
21606  nk_textedit_layout_row(&r, state, 0, row_height, font);
21607  if (single_line) {
21608  find->first_char = 0;
21609  find->length = z;
21610  } else {
21611  while (i < z) {
21612  prev_start = i;
21613  i += r.num_chars;
21614  nk_textedit_layout_row(&r, state, i, row_height, font);
21615  }
21616 
21617  find->first_char = i;
21618  find->length = r.num_chars;
21619  }
21620  find->x = r.x1;
21621  find->y = r.ymin;
21622  find->height = r.ymax - r.ymin;
21623  find->prev_first = prev_start;
21624  return;
21625  }
21626 
21627  /* search rows to find the one that straddles character n */
21628  find->y = 0;
21629 
21630  for(;;) {
21631  nk_textedit_layout_row(&r, state, i, row_height, font);
21632  if (n < i + r.num_chars) break;
21633  prev_start = i;
21634  i += r.num_chars;
21635  find->y += r.baseline_y_delta;
21636  }
21637 
21638  find->first_char = first = i;
21639  find->length = r.num_chars;
21640  find->height = r.ymax - r.ymin;
21641  find->prev_first = prev_start;
21642 
21643  /* now scan to find xpos */
21644  find->x = r.x0;
21645  for (i=0; first+i < n; ++i)
21646  find->x += nk_textedit_get_width(state, first, i, font);
21647 }
21648 NK_INTERN void
21649 nk_textedit_clamp(struct nk_text_edit *state)
21650 {
21651  /* make the selection/cursor state valid if client altered the string */
21652  int n = state->string.len;
21653  if (NK_TEXT_HAS_SELECTION(state)) {
21654  if (state->select_start > n) state->select_start = n;
21655  if (state->select_end > n) state->select_end = n;
21656  /* if clamping forced them to be equal, move the cursor to match */
21657  if (state->select_start == state->select_end)
21658  state->cursor = state->select_start;
21659  }
21660  if (state->cursor > n) state->cursor = n;
21661 }
21662 NK_API void
21663 nk_textedit_delete(struct nk_text_edit *state, int where, int len)
21664 {
21665  /* delete characters while updating undo */
21666  nk_textedit_makeundo_delete(state, where, len);
21667  nk_str_delete_runes(&state->string, where, len);
21668  state->has_preferred_x = 0;
21669 }
21670 NK_API void
21672 {
21673  /* delete the section */
21674  nk_textedit_clamp(state);
21675  if (NK_TEXT_HAS_SELECTION(state)) {
21676  if (state->select_start < state->select_end) {
21677  nk_textedit_delete(state, state->select_start,
21678  state->select_end - state->select_start);
21679  state->select_end = state->cursor = state->select_start;
21680  } else {
21681  nk_textedit_delete(state, state->select_end,
21682  state->select_start - state->select_end);
21683  state->select_start = state->cursor = state->select_end;
21684  }
21685  state->has_preferred_x = 0;
21686  }
21687 }
21688 NK_INTERN void
21689 nk_textedit_sortselection(struct nk_text_edit *state)
21690 {
21691  /* canonicalize the selection so start <= end */
21692  if (state->select_end < state->select_start) {
21693  int temp = state->select_end;
21694  state->select_end = state->select_start;
21695  state->select_start = temp;
21696  }
21697 }
21698 NK_INTERN void
21699 nk_textedit_move_to_first(struct nk_text_edit *state)
21700 {
21701  /* move cursor to first character of selection */
21702  if (NK_TEXT_HAS_SELECTION(state)) {
21703  nk_textedit_sortselection(state);
21704  state->cursor = state->select_start;
21705  state->select_end = state->select_start;
21706  state->has_preferred_x = 0;
21707  }
21708 }
21709 NK_INTERN void
21710 nk_textedit_move_to_last(struct nk_text_edit *state)
21711 {
21712  /* move cursor to last character of selection */
21713  if (NK_TEXT_HAS_SELECTION(state)) {
21714  nk_textedit_sortselection(state);
21715  nk_textedit_clamp(state);
21716  state->cursor = state->select_end;
21717  state->select_start = state->select_end;
21718  state->has_preferred_x = 0;
21719  }
21720 }
21721 NK_INTERN int
21722 nk_is_word_boundary( struct nk_text_edit *state, int idx)
21723 {
21724  int len;
21725  nk_rune c;
21726  if (idx <= 0) return 1;
21727  if (!nk_str_at_rune(&state->string, idx, &c, &len)) return 1;
21728  return (c == ' ' || c == '\t' ||c == 0x3000 || c == ',' || c == ';' ||
21729  c == '(' || c == ')' || c == '{' || c == '}' || c == '[' || c == ']' ||
21730  c == '|');
21731 }
21732 NK_INTERN int
21733 nk_textedit_move_to_word_previous(struct nk_text_edit *state)
21734 {
21735  int c = state->cursor - 1;
21736  while( c >= 0 && !nk_is_word_boundary(state, c))
21737  --c;
21738 
21739  if( c < 0 )
21740  c = 0;
21741 
21742  return c;
21743 }
21744 NK_INTERN int
21745 nk_textedit_move_to_word_next(struct nk_text_edit *state)
21746 {
21747  const int len = state->string.len;
21748  int c = state->cursor+1;
21749  while( c < len && !nk_is_word_boundary(state, c))
21750  ++c;
21751 
21752  if( c > len )
21753  c = len;
21754 
21755  return c;
21756 }
21757 NK_INTERN void
21758 nk_textedit_prep_selection_at_cursor(struct nk_text_edit *state)
21759 {
21760  /* update selection and cursor to match each other */
21761  if (!NK_TEXT_HAS_SELECTION(state))
21762  state->select_start = state->select_end = state->cursor;
21763  else state->cursor = state->select_end;
21764 }
21765 NK_API int
21766 nk_textedit_cut(struct nk_text_edit *state)
21767 {
21768  /* API cut: delete selection */
21769  if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
21770  return 0;
21771  if (NK_TEXT_HAS_SELECTION(state)) {
21772  nk_textedit_delete_selection(state); /* implicitly clamps */
21773  state->has_preferred_x = 0;
21774  return 1;
21775  }
21776  return 0;
21777 }
21778 NK_API int
21779 nk_textedit_paste(struct nk_text_edit *state, char const *ctext, int len)
21780 {
21781  /* API paste: replace existing selection with passed-in text */
21782  int glyphs;
21783  const char *text = (const char *) ctext;
21784  if (state->mode == NK_TEXT_EDIT_MODE_VIEW) return 0;
21785 
21786  /* if there's a selection, the paste should delete it */
21787  nk_textedit_clamp(state);
21789 
21790  /* try to insert the characters */
21791  glyphs = nk_utf_len(ctext, len);
21792  if (nk_str_insert_text_char(&state->string, state->cursor, text, len)) {
21793  nk_textedit_makeundo_insert(state, state->cursor, glyphs);
21794  state->cursor += len;
21795  state->has_preferred_x = 0;
21796  return 1;
21797  }
21798  /* remove the undo since we didn't actually insert the characters */
21799  if (state->undo.undo_point)
21800  --state->undo.undo_point;
21801  return 0;
21802 }
21803 NK_API void
21804 nk_textedit_text(struct nk_text_edit *state, const char *text, int total_len)
21805 {
21806  nk_rune unicode;
21807  int glyph_len;
21808  int text_len = 0;
21809 
21810  NK_ASSERT(state);
21811  NK_ASSERT(text);
21812  if (!text || !total_len || state->mode == NK_TEXT_EDIT_MODE_VIEW) return;
21813 
21814  glyph_len = nk_utf_decode(text, &unicode, total_len);
21815  while ((text_len < total_len) && glyph_len)
21816  {
21817  /* don't insert a backward delete, just process the event */
21818  if (unicode == 127) goto next;
21819  /* can't add newline in single-line mode */
21820  if (unicode == '\n' && state->single_line) goto next;
21821  /* filter incoming text */
21822  if (state->filter && !state->filter(state, unicode)) goto next;
21823 
21824  if (!NK_TEXT_HAS_SELECTION(state) &&
21825  state->cursor < state->string.len)
21826  {
21827  if (state->mode == NK_TEXT_EDIT_MODE_REPLACE) {
21828  nk_textedit_makeundo_replace(state, state->cursor, 1, 1);
21829  nk_str_delete_runes(&state->string, state->cursor, 1);
21830  }
21831  if (nk_str_insert_text_utf8(&state->string, state->cursor,
21832  text+text_len, 1))
21833  {
21834  ++state->cursor;
21835  state->has_preferred_x = 0;
21836  }
21837  } else {
21838  nk_textedit_delete_selection(state); /* implicitly clamps */
21839  if (nk_str_insert_text_utf8(&state->string, state->cursor,
21840  text+text_len, 1))
21841  {
21842  nk_textedit_makeundo_insert(state, state->cursor, 1);
21843  ++state->cursor;
21844  state->has_preferred_x = 0;
21845  }
21846  }
21847  next:
21848  text_len += glyph_len;
21849  glyph_len = nk_utf_decode(text + text_len, &unicode, total_len-text_len);
21850  }
21851 }
21852 NK_LIB void
21853 nk_textedit_key(struct nk_text_edit *state, enum nk_keys key, int shift_mod,
21854  const struct nk_user_font *font, float row_height)
21855 {
21856 retry:
21857  switch (key)
21858  {
21859  case NK_KEY_NONE:
21860  case NK_KEY_CTRL:
21861  case NK_KEY_ENTER:
21862  case NK_KEY_SHIFT:
21863  case NK_KEY_TAB:
21864  case NK_KEY_COPY:
21865  case NK_KEY_CUT:
21866  case NK_KEY_PASTE:
21867  case NK_KEY_MAX:
21868  default: break;
21869  case NK_KEY_TEXT_UNDO:
21870  nk_textedit_undo(state);
21871  state->has_preferred_x = 0;
21872  break;
21873 
21874  case NK_KEY_TEXT_REDO:
21875  nk_textedit_redo(state);
21876  state->has_preferred_x = 0;
21877  break;
21878 
21880  nk_textedit_select_all(state);
21881  state->has_preferred_x = 0;
21882  break;
21883 
21885  if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
21886  state->mode = NK_TEXT_EDIT_MODE_INSERT;
21887  break;
21889  if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
21891  break;
21893  if (state->mode == NK_TEXT_EDIT_MODE_INSERT ||
21894  state->mode == NK_TEXT_EDIT_MODE_REPLACE)
21895  state->mode = NK_TEXT_EDIT_MODE_VIEW;
21896  break;
21897 
21898  case NK_KEY_LEFT:
21899  if (shift_mod) {
21900  nk_textedit_clamp(state);
21901  nk_textedit_prep_selection_at_cursor(state);
21902  /* move selection left */
21903  if (state->select_end > 0)
21904  --state->select_end;
21905  state->cursor = state->select_end;
21906  state->has_preferred_x = 0;
21907  } else {
21908  /* if currently there's a selection,
21909  * move cursor to start of selection */
21910  if (NK_TEXT_HAS_SELECTION(state))
21911  nk_textedit_move_to_first(state);
21912  else if (state->cursor > 0)
21913  --state->cursor;
21914  state->has_preferred_x = 0;
21915  } break;
21916 
21917  case NK_KEY_RIGHT:
21918  if (shift_mod) {
21919  nk_textedit_prep_selection_at_cursor(state);
21920  /* move selection right */
21921  ++state->select_end;
21922  nk_textedit_clamp(state);
21923  state->cursor = state->select_end;
21924  state->has_preferred_x = 0;
21925  } else {
21926  /* if currently there's a selection,
21927  * move cursor to end of selection */
21928  if (NK_TEXT_HAS_SELECTION(state))
21929  nk_textedit_move_to_last(state);
21930  else ++state->cursor;
21931  nk_textedit_clamp(state);
21932  state->has_preferred_x = 0;
21933  } break;
21934 
21935  case NK_KEY_TEXT_WORD_LEFT:
21936  if (shift_mod) {
21937  if( !NK_TEXT_HAS_SELECTION( state ) )
21938  nk_textedit_prep_selection_at_cursor(state);
21939  state->cursor = nk_textedit_move_to_word_previous(state);
21940  state->select_end = state->cursor;
21941  nk_textedit_clamp(state );
21942  } else {
21943  if (NK_TEXT_HAS_SELECTION(state))
21944  nk_textedit_move_to_first(state);
21945  else {
21946  state->cursor = nk_textedit_move_to_word_previous(state);
21947  nk_textedit_clamp(state );
21948  }
21949  } break;
21950 
21952  if (shift_mod) {
21953  if( !NK_TEXT_HAS_SELECTION( state ) )
21954  nk_textedit_prep_selection_at_cursor(state);
21955  state->cursor = nk_textedit_move_to_word_next(state);
21956  state->select_end = state->cursor;
21957  nk_textedit_clamp(state);
21958  } else {
21959  if (NK_TEXT_HAS_SELECTION(state))
21960  nk_textedit_move_to_last(state);
21961  else {
21962  state->cursor = nk_textedit_move_to_word_next(state);
21963  nk_textedit_clamp(state );
21964  }
21965  } break;
21966 
21967  case NK_KEY_DOWN: {
21968  struct nk_text_find find;
21969  struct nk_text_edit_row row;
21970  int i, sel = shift_mod;
21971 
21972  if (state->single_line) {
21973  /* on windows, up&down in single-line behave like left&right */
21974  key = NK_KEY_RIGHT;
21975  goto retry;
21976  }
21977 
21978  if (sel)
21979  nk_textedit_prep_selection_at_cursor(state);
21980  else if (NK_TEXT_HAS_SELECTION(state))
21981  nk_textedit_move_to_last(state);
21982 
21983  /* compute current position of cursor point */
21984  nk_textedit_clamp(state);
21985  nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
21986  font, row_height);
21987 
21988  /* now find character position down a row */
21989  if (find.length)
21990  {
21991  float x;
21992  float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
21993  int start = find.first_char + find.length;
21994 
21995  state->cursor = start;
21996  nk_textedit_layout_row(&row, state, state->cursor, row_height, font);
21997  x = row.x0;
21998 
21999  for (i=0; i < row.num_chars && x < row.x1; ++i) {
22000  float dx = nk_textedit_get_width(state, start, i, font);
22001  x += dx;
22002  if (x > goal_x)
22003  break;
22004  ++state->cursor;
22005  }
22006  nk_textedit_clamp(state);
22007 
22008  state->has_preferred_x = 1;
22009  state->preferred_x = goal_x;
22010  if (sel)
22011  state->select_end = state->cursor;
22012  }
22013  } break;
22014 
22015  case NK_KEY_UP: {
22016  struct nk_text_find find;
22017  struct nk_text_edit_row row;
22018  int i, sel = shift_mod;
22019 
22020  if (state->single_line) {
22021  /* on windows, up&down become left&right */
22022  key = NK_KEY_LEFT;
22023  goto retry;
22024  }
22025 
22026  if (sel)
22027  nk_textedit_prep_selection_at_cursor(state);
22028  else if (NK_TEXT_HAS_SELECTION(state))
22029  nk_textedit_move_to_first(state);
22030 
22031  /* compute current position of cursor point */
22032  nk_textedit_clamp(state);
22033  nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
22034  font, row_height);
22035 
22036  /* can only go up if there's a previous row */
22037  if (find.prev_first != find.first_char) {
22038  /* now find character position up a row */
22039  float x;
22040  float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
22041 
22042  state->cursor = find.prev_first;
22043  nk_textedit_layout_row(&row, state, state->cursor, row_height, font);
22044  x = row.x0;
22045 
22046  for (i=0; i < row.num_chars && x < row.x1; ++i) {
22047  float dx = nk_textedit_get_width(state, find.prev_first, i, font);
22048  x += dx;
22049  if (x > goal_x)
22050  break;
22051  ++state->cursor;
22052  }
22053  nk_textedit_clamp(state);
22054 
22055  state->has_preferred_x = 1;
22056  state->preferred_x = goal_x;
22057  if (sel) state->select_end = state->cursor;
22058  }
22059  } break;
22060 
22061  case NK_KEY_DEL:
22062  if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
22063  break;
22064  if (NK_TEXT_HAS_SELECTION(state))
22066  else {
22067  int n = state->string.len;
22068  if (state->cursor < n)
22069  nk_textedit_delete(state, state->cursor, 1);
22070  }
22071  state->has_preferred_x = 0;
22072  break;
22073 
22074  case NK_KEY_BACKSPACE:
22075  if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
22076  break;
22077  if (NK_TEXT_HAS_SELECTION(state))
22079  else {
22080  nk_textedit_clamp(state);
22081  if (state->cursor > 0) {
22082  nk_textedit_delete(state, state->cursor-1, 1);
22083  --state->cursor;
22084  }
22085  }
22086  state->has_preferred_x = 0;
22087  break;
22088 
22089  case NK_KEY_TEXT_START:
22090  if (shift_mod) {
22091  nk_textedit_prep_selection_at_cursor(state);
22092  state->cursor = state->select_end = 0;
22093  state->has_preferred_x = 0;
22094  } else {
22095  state->cursor = state->select_start = state->select_end = 0;
22096  state->has_preferred_x = 0;
22097  }
22098  break;
22099 
22100  case NK_KEY_TEXT_END:
22101  if (shift_mod) {
22102  nk_textedit_prep_selection_at_cursor(state);
22103  state->cursor = state->select_end = state->string.len;
22104  state->has_preferred_x = 0;
22105  } else {
22106  state->cursor = state->string.len;
22107  state->select_start = state->select_end = 0;
22108  state->has_preferred_x = 0;
22109  }
22110  break;
22111 
22112  case NK_KEY_TEXT_LINE_START: {
22113  if (shift_mod) {
22114  struct nk_text_find find;
22115  nk_textedit_clamp(state);
22116  nk_textedit_prep_selection_at_cursor(state);
22117  if (state->string.len && state->cursor == state->string.len)
22118  --state->cursor;
22119  nk_textedit_find_charpos(&find, state,state->cursor, state->single_line,
22120  font, row_height);
22121  state->cursor = state->select_end = find.first_char;
22122  state->has_preferred_x = 0;
22123  } else {
22124  struct nk_text_find find;
22125  if (state->string.len && state->cursor == state->string.len)
22126  --state->cursor;
22127  nk_textedit_clamp(state);
22128  nk_textedit_move_to_first(state);
22129  nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
22130  font, row_height);
22131  state->cursor = find.first_char;
22132  state->has_preferred_x = 0;
22133  }
22134  } break;
22135 
22136  case NK_KEY_TEXT_LINE_END: {
22137  if (shift_mod) {
22138  struct nk_text_find find;
22139  nk_textedit_clamp(state);
22140  nk_textedit_prep_selection_at_cursor(state);
22141  nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
22142  font, row_height);
22143  state->has_preferred_x = 0;
22144  state->cursor = find.first_char + find.length;
22145  if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n')
22146  --state->cursor;
22147  state->select_end = state->cursor;
22148  } else {
22149  struct nk_text_find find;
22150  nk_textedit_clamp(state);
22151  nk_textedit_move_to_first(state);
22152  nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
22153  font, row_height);
22154 
22155  state->has_preferred_x = 0;
22156  state->cursor = find.first_char + find.length;
22157  if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n')
22158  --state->cursor;
22159  }} break;
22160  }
22161 }
22162 NK_INTERN void
22163 nk_textedit_flush_redo(struct nk_text_undo_state *state)
22164 {
22167 }
22168 NK_INTERN void
22169 nk_textedit_discard_undo(struct nk_text_undo_state *state)
22170 {
22171  /* discard the oldest entry in the undo list */
22172  if (state->undo_point > 0) {
22173  /* if the 0th undo state has characters, clean those up */
22174  if (state->undo_rec[0].char_storage >= 0) {
22175  int n = state->undo_rec[0].insert_length, i;
22176  /* delete n characters from all other records */
22177  state->undo_char_point = (short)(state->undo_char_point - n);
22178  NK_MEMCPY(state->undo_char, state->undo_char + n,
22179  (nk_size)state->undo_char_point*sizeof(nk_rune));
22180  for (i=0; i < state->undo_point; ++i) {
22181  if (state->undo_rec[i].char_storage >= 0)
22182  state->undo_rec[i].char_storage = (short)
22183  (state->undo_rec[i].char_storage - n);
22184  }
22185  }
22186  --state->undo_point;
22187  NK_MEMCPY(state->undo_rec, state->undo_rec+1,
22188  (nk_size)((nk_size)state->undo_point * sizeof(state->undo_rec[0])));
22189  }
22190 }
22191 NK_INTERN void
22192 nk_textedit_discard_redo(struct nk_text_undo_state *state)
22193 {
22194 /* discard the oldest entry in the redo list--it's bad if this
22195  ever happens, but because undo & redo have to store the actual
22196  characters in different cases, the redo character buffer can
22197  fill up even though the undo buffer didn't */
22198  nk_size num;
22199  int k = NK_TEXTEDIT_UNDOSTATECOUNT-1;
22200  if (state->redo_point <= k) {
22201  /* if the k'th undo state has characters, clean those up */
22202  if (state->undo_rec[k].char_storage >= 0) {
22203  int n = state->undo_rec[k].insert_length, i;
22204  /* delete n characters from all other records */
22205  state->redo_char_point = (short)(state->redo_char_point + n);
22207  NK_MEMCPY(state->undo_char + state->redo_char_point,
22208  state->undo_char + state->redo_char_point-n, num * sizeof(char));
22209  for (i = state->redo_point; i < k; ++i) {
22210  if (state->undo_rec[i].char_storage >= 0) {
22211  state->undo_rec[i].char_storage = (short)
22212  (state->undo_rec[i].char_storage + n);
22213  }
22214  }
22215  }
22216  ++state->redo_point;
22217  num = (nk_size)(NK_TEXTEDIT_UNDOSTATECOUNT - state->redo_point);
22218  if (num) NK_MEMCPY(state->undo_rec + state->redo_point-1,
22219  state->undo_rec + state->redo_point, num * sizeof(state->undo_rec[0]));
22220  }
22221 }
22223 nk_textedit_create_undo_record(struct nk_text_undo_state *state, int numchars)
22224 {
22225  /* any time we create a new undo record, we discard redo*/
22226  nk_textedit_flush_redo(state);
22227 
22228  /* if we have no free records, we have to make room,
22229  * by sliding the existing records down */
22230  if (state->undo_point == NK_TEXTEDIT_UNDOSTATECOUNT)
22231  nk_textedit_discard_undo(state);
22232 
22233  /* if the characters to store won't possibly fit in the buffer,
22234  * we can't undo */
22235  if (numchars > NK_TEXTEDIT_UNDOCHARCOUNT) {
22236  state->undo_point = 0;
22237  state->undo_char_point = 0;
22238  return 0;
22239  }
22240 
22241  /* if we don't have enough free characters in the buffer,
22242  * we have to make room */
22243  while (state->undo_char_point + numchars > NK_TEXTEDIT_UNDOCHARCOUNT)
22244  nk_textedit_discard_undo(state);
22245  return &state->undo_rec[state->undo_point++];
22246 }
22248 nk_textedit_createundo(struct nk_text_undo_state *state, int pos,
22249  int insert_len, int delete_len)
22250 {
22251  struct nk_text_undo_record *r = nk_textedit_create_undo_record(state, insert_len);
22252  if (r == 0)
22253  return 0;
22254 
22255  r->where = pos;
22256  r->insert_length = (short) insert_len;
22257  r->delete_length = (short) delete_len;
22258 
22259  if (insert_len == 0) {
22260  r->char_storage = -1;
22261  return 0;
22262  } else {
22263  r->char_storage = state->undo_char_point;
22264  state->undo_char_point = (short)(state->undo_char_point + insert_len);
22265  return &state->undo_char[r->char_storage];
22266  }
22267 }
22268 NK_API void
22269 nk_textedit_undo(struct nk_text_edit *state)
22270 {
22271  struct nk_text_undo_state *s = &state->undo;
22272  struct nk_text_undo_record u, *r;
22273  if (s->undo_point == 0)
22274  return;
22275 
22276  /* we need to do two things: apply the undo record, and create a redo record */
22277  u = s->undo_rec[s->undo_point-1];
22278  r = &s->undo_rec[s->redo_point-1];
22279  r->char_storage = -1;
22280 
22281  r->insert_length = u.delete_length;
22282  r->delete_length = u.insert_length;
22283  r->where = u.where;
22284 
22285  if (u.delete_length)
22286  {
22287  /* if the undo record says to delete characters, then the redo record will
22288  need to re-insert the characters that get deleted, so we need to store
22289  them.
22290  there are three cases:
22291  - there's enough room to store the characters
22292  - characters stored for *redoing* don't leave room for redo
22293  - characters stored for *undoing* don't leave room for redo
22294  if the last is true, we have to bail */
22295  if (s->undo_char_point + u.delete_length >= NK_TEXTEDIT_UNDOCHARCOUNT) {
22296  /* the undo records take up too much character space; there's no space
22297  * to store the redo characters */
22298  r->insert_length = 0;
22299  } else {
22300  int i;
22301  /* there's definitely room to store the characters eventually */
22302  while (s->undo_char_point + u.delete_length > s->redo_char_point) {
22303  /* there's currently not enough room, so discard a redo record */
22304  nk_textedit_discard_redo(s);
22305  /* should never happen: */
22307  return;
22308  }
22309 
22310  r = &s->undo_rec[s->redo_point-1];
22311  r->char_storage = (short)(s->redo_char_point - u.delete_length);
22312  s->redo_char_point = (short)(s->redo_char_point - u.delete_length);
22313 
22314  /* now save the characters */
22315  for (i=0; i < u.delete_length; ++i)
22316  s->undo_char[r->char_storage + i] =
22317  nk_str_rune_at(&state->string, u.where + i);
22318  }
22319  /* now we can carry out the deletion */
22320  nk_str_delete_runes(&state->string, u.where, u.delete_length);
22321  }
22322 
22323  /* check type of recorded action: */
22324  if (u.insert_length) {
22325  /* easy case: was a deletion, so we need to insert n characters */
22326  nk_str_insert_text_runes(&state->string, u.where,
22327  &s->undo_char[u.char_storage], u.insert_length);
22328  s->undo_char_point = (short)(s->undo_char_point - u.insert_length);
22329  }
22330  state->cursor = (short)(u.where + u.insert_length);
22331 
22332  s->undo_point--;
22333  s->redo_point--;
22334 }
22335 NK_API void
22336 nk_textedit_redo(struct nk_text_edit *state)
22337 {
22338  struct nk_text_undo_state *s = &state->undo;
22339  struct nk_text_undo_record *u, r;
22341  return;
22342 
22343  /* we need to do two things: apply the redo record, and create an undo record */
22344  u = &s->undo_rec[s->undo_point];
22345  r = s->undo_rec[s->redo_point];
22346 
22347  /* we KNOW there must be room for the undo record, because the redo record
22348  was derived from an undo record */
22351  u->where = r.where;
22352  u->char_storage = -1;
22353 
22354  if (r.delete_length) {
22355  /* the redo record requires us to delete characters, so the undo record
22356  needs to store the characters */
22357  if (s->undo_char_point + u->insert_length > s->redo_char_point) {
22358  u->insert_length = 0;
22359  u->delete_length = 0;
22360  } else {
22361  int i;
22362  u->char_storage = s->undo_char_point;
22363  s->undo_char_point = (short)(s->undo_char_point + u->insert_length);
22364 
22365  /* now save the characters */
22366  for (i=0; i < u->insert_length; ++i) {
22367  s->undo_char[u->char_storage + i] =
22368  nk_str_rune_at(&state->string, u->where + i);
22369  }
22370  }
22372  }
22373 
22374  if (r.insert_length) {
22375  /* easy case: need to insert n characters */
22378  }
22379  state->cursor = r.where + r.insert_length;
22380 
22381  s->undo_point++;
22382  s->redo_point++;
22383 }
22384 NK_INTERN void
22385 nk_textedit_makeundo_insert(struct nk_text_edit *state, int where, int length)
22386 {
22387  nk_textedit_createundo(&state->undo, where, 0, length);
22388 }
22389 NK_INTERN void
22390 nk_textedit_makeundo_delete(struct nk_text_edit *state, int where, int length)
22391 {
22392  int i;
22393  nk_rune *p = nk_textedit_createundo(&state->undo, where, length, 0);
22394  if (p) {
22395  for (i=0; i < length; ++i)
22396  p[i] = nk_str_rune_at(&state->string, where+i);
22397  }
22398 }
22399 NK_INTERN void
22400 nk_textedit_makeundo_replace(struct nk_text_edit *state, int where,
22401  int old_length, int new_length)
22402 {
22403  int i;
22404  nk_rune *p = nk_textedit_createundo(&state->undo, where, old_length, new_length);
22405  if (p) {
22406  for (i=0; i < old_length; ++i)
22407  p[i] = nk_str_rune_at(&state->string, where+i);
22408  }
22409 }
22410 NK_LIB void
22411 nk_textedit_clear_state(struct nk_text_edit *state, enum nk_text_edit_type type,
22412  nk_plugin_filter filter)
22413 {
22414  /* reset the state to default */
22415  state->undo.undo_point = 0;
22416  state->undo.undo_char_point = 0;
22419  state->select_end = state->select_start = 0;
22420  state->cursor = 0;
22421  state->has_preferred_x = 0;
22422  state->preferred_x = 0;
22423  state->cursor_at_end_of_line = 0;
22424  state->initialized = 1;
22425  state->single_line = (unsigned char)(type == NK_TEXT_EDIT_SINGLE_LINE);
22426  state->mode = NK_TEXT_EDIT_MODE_VIEW;
22427  state->filter = filter;
22428  state->scrollbar = nk_vec2(0,0);
22429 }
22430 NK_API void
22431 nk_textedit_init_fixed(struct nk_text_edit *state, void *memory, nk_size size)
22432 {
22433  NK_ASSERT(state);
22434  NK_ASSERT(memory);
22435  if (!state || !memory || !size) return;
22436  NK_MEMSET(state, 0, sizeof(struct nk_text_edit));
22437  nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
22438  nk_str_init_fixed(&state->string, memory, size);
22439 }
22440 NK_API void
22441 nk_textedit_init(struct nk_text_edit *state, struct nk_allocator *alloc, nk_size size)
22442 {
22443  NK_ASSERT(state);
22444  NK_ASSERT(alloc);
22445  if (!state || !alloc) return;
22446  NK_MEMSET(state, 0, sizeof(struct nk_text_edit));
22447  nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
22448  nk_str_init(&state->string, alloc, size);
22449 }
22450 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
22451 NK_API void
22452 nk_textedit_init_default(struct nk_text_edit *state)
22453 {
22454  NK_ASSERT(state);
22455  if (!state) return;
22456  NK_MEMSET(state, 0, sizeof(struct nk_text_edit));
22457  nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
22458  nk_str_init_default(&state->string);
22459 }
22460 #endif
22461 NK_API void
22462 nk_textedit_select_all(struct nk_text_edit *state)
22463 {
22464  NK_ASSERT(state);
22465  state->select_start = 0;
22466  state->select_end = state->string.len;
22467 }
22468 NK_API void
22469 nk_textedit_free(struct nk_text_edit *state)
22470 {
22471  NK_ASSERT(state);
22472  if (!state) return;
22473  nk_str_free(&state->string);
22474 }
22475 
22476 
22477 
22478 
22479 
22480 /* ===============================================================
22481  *
22482  * FILTER
22483  *
22484  * ===============================================================*/
22485 NK_API int
22486 nk_filter_default(const struct nk_text_edit *box, nk_rune unicode)
22487 {
22488  NK_UNUSED(unicode);
22489  NK_UNUSED(box);
22490  return nk_true;
22491 }
22492 NK_API int
22493 nk_filter_ascii(const struct nk_text_edit *box, nk_rune unicode)
22494 {
22495  NK_UNUSED(box);
22496  if (unicode > 128) return nk_false;
22497  else return nk_true;
22498 }
22499 NK_API int
22500 nk_filter_float(const struct nk_text_edit *box, nk_rune unicode)
22501 {
22502  NK_UNUSED(box);
22503  if ((unicode < '0' || unicode > '9') && unicode != '.' && unicode != '-')
22504  return nk_false;
22505  else return nk_true;
22506 }
22507 NK_API int
22508 nk_filter_decimal(const struct nk_text_edit *box, nk_rune unicode)
22509 {
22510  NK_UNUSED(box);
22511  if ((unicode < '0' || unicode > '9') && unicode != '-')
22512  return nk_false;
22513  else return nk_true;
22514 }
22515 NK_API int
22516 nk_filter_hex(const struct nk_text_edit *box, nk_rune unicode)
22517 {
22518  NK_UNUSED(box);
22519  if ((unicode < '0' || unicode > '9') &&
22520  (unicode < 'a' || unicode > 'f') &&
22521  (unicode < 'A' || unicode > 'F'))
22522  return nk_false;
22523  else return nk_true;
22524 }
22525 NK_API int
22526 nk_filter_oct(const struct nk_text_edit *box, nk_rune unicode)
22527 {
22528  NK_UNUSED(box);
22529  if (unicode < '0' || unicode > '7')
22530  return nk_false;
22531  else return nk_true;
22532 }
22533 NK_API int
22534 nk_filter_binary(const struct nk_text_edit *box, nk_rune unicode)
22535 {
22536  NK_UNUSED(box);
22537  if (unicode != '0' && unicode != '1')
22538  return nk_false;
22539  else return nk_true;
22540 }
22541 
22542 /* ===============================================================
22543  *
22544  * EDIT
22545  *
22546  * ===============================================================*/
22547 NK_LIB void
22548 nk_edit_draw_text(struct nk_command_buffer *out,
22549  const struct nk_style_edit *style, float pos_x, float pos_y,
22550  float x_offset, const char *text, int byte_len, float row_height,
22551  const struct nk_user_font *font, struct nk_color background,
22552  struct nk_color foreground, int is_selected)
22553 {
22554  NK_ASSERT(out);
22555  NK_ASSERT(font);
22556  NK_ASSERT(style);
22557  if (!text || !byte_len || !out || !style) return;
22558 
22559  {int glyph_len = 0;
22560  nk_rune unicode = 0;
22561  int text_len = 0;
22562  float line_width = 0;
22563  float glyph_width;
22564  const char *line = text;
22565  float line_offset = 0;
22566  int line_count = 0;
22567 
22568  struct nk_text txt;
22569  txt.padding = nk_vec2(0,0);
22570  txt.background = background;
22571  txt.text = foreground;
22572 
22573  glyph_len = nk_utf_decode(text+text_len, &unicode, byte_len-text_len);
22574  if (!glyph_len) return;
22575  while ((text_len < byte_len) && glyph_len)
22576  {
22577  if (unicode == '\n') {
22578  /* new line separator so draw previous line */
22579  struct nk_rect label;
22580  label.y = pos_y + line_offset;
22581  label.h = row_height;
22582  label.w = line_width;
22583  label.x = pos_x;
22584  if (!line_count)
22585  label.x += x_offset;
22586 
22587  if (is_selected) /* selection needs to draw different background color */
22588  nk_fill_rect(out, label, 0, background);
22589  nk_widget_text(out, label, line, (int)((text + text_len) - line),
22590  &txt, NK_TEXT_CENTERED, font);
22591 
22592  text_len++;
22593  line_count++;
22594  line_width = 0;
22595  line = text + text_len;
22596  line_offset += row_height;
22597  glyph_len = nk_utf_decode(text + text_len, &unicode, (int)(byte_len-text_len));
22598  continue;
22599  }
22600  if (unicode == '\r') {
22601  text_len++;
22602  glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len);
22603  continue;
22604  }
22605  glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len);
22606  line_width += (float)glyph_width;
22607  text_len += glyph_len;
22608  glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len);
22609  continue;
22610  }
22611  if (line_width > 0) {
22612  /* draw last line */
22613  struct nk_rect label;
22614  label.y = pos_y + line_offset;
22615  label.h = row_height;
22616  label.w = line_width;
22617  label.x = pos_x;
22618  if (!line_count)
22619  label.x += x_offset;
22620 
22621  if (is_selected)
22622  nk_fill_rect(out, label, 0, background);
22623  nk_widget_text(out, label, line, (int)((text + text_len) - line),
22624  &txt, NK_TEXT_LEFT, font);
22625  }}
22626 }
22628 nk_do_edit(nk_flags *state, struct nk_command_buffer *out,
22629  struct nk_rect bounds, nk_flags flags, nk_plugin_filter filter,
22630  struct nk_text_edit *edit, const struct nk_style_edit *style,
22631  struct nk_input *in, const struct nk_user_font *font)
22632 {
22633  struct nk_rect area;
22634  nk_flags ret = 0;
22635  float row_height;
22636  char prev_state = 0;
22637  char is_hovered = 0;
22638  char select_all = 0;
22639  char cursor_follow = 0;
22640  struct nk_rect old_clip;
22641  struct nk_rect clip;
22642 
22643  NK_ASSERT(state);
22644  NK_ASSERT(out);
22645  NK_ASSERT(style);
22646  if (!state || !out || !style)
22647  return ret;
22648 
22649  /* visible text area calculation */
22650  area.x = bounds.x + style->padding.x + style->border;
22651  area.y = bounds.y + style->padding.y + style->border;
22652  area.w = bounds.w - (2.0f * style->padding.x + 2 * style->border);
22653  area.h = bounds.h - (2.0f * style->padding.y + 2 * style->border);
22654  if (flags & NK_EDIT_MULTILINE)
22655  area.w = NK_MAX(0, area.w - style->scrollbar_size.x);
22656  row_height = (flags & NK_EDIT_MULTILINE)? font->height + style->row_padding: area.h;
22657 
22658  /* calculate clipping rectangle */
22659  old_clip = out->clip;
22660  nk_unify(&clip, &old_clip, area.x, area.y, area.x + area.w, area.y + area.h);
22661 
22662  /* update edit state */
22663  prev_state = (char)edit->active;
22664  is_hovered = (char)nk_input_is_mouse_hovering_rect(in, bounds);
22666  edit->active = NK_INBOX(in->mouse.pos.x, in->mouse.pos.y,
22667  bounds.x, bounds.y, bounds.w, bounds.h);
22668  }
22669 
22670  /* (de)activate text editor */
22671  if (!prev_state && edit->active) {
22672  const enum nk_text_edit_type type = (flags & NK_EDIT_MULTILINE) ?
22674  nk_textedit_clear_state(edit, type, filter);
22675  if (flags & NK_EDIT_AUTO_SELECT)
22676  select_all = nk_true;
22677  if (flags & NK_EDIT_GOTO_END_ON_ACTIVATE) {
22678  edit->cursor = edit->string.len;
22679  in = 0;
22680  }
22681  } else if (!edit->active) edit->mode = NK_TEXT_EDIT_MODE_VIEW;
22682  if (flags & NK_EDIT_READ_ONLY)
22683  edit->mode = NK_TEXT_EDIT_MODE_VIEW;
22684  else if (flags & NK_EDIT_ALWAYS_INSERT_MODE)
22686 
22687  ret = (edit->active) ? NK_EDIT_ACTIVE: NK_EDIT_INACTIVE;
22688  if (prev_state != edit->active)
22689  ret |= (edit->active) ? NK_EDIT_ACTIVATED: NK_EDIT_DEACTIVATED;
22690 
22691  /* handle user input */
22692  if (edit->active && in)
22693  {
22694  int shift_mod = in->keyboard.keys[NK_KEY_SHIFT].down;
22695  const float mouse_x = (in->mouse.pos.x - area.x) + edit->scrollbar.x;
22696  const float mouse_y = (in->mouse.pos.y - area.y) + edit->scrollbar.y;
22697 
22698  /* mouse click handler */
22699  is_hovered = (char)nk_input_is_mouse_hovering_rect(in, area);
22700  if (select_all) {
22701  nk_textedit_select_all(edit);
22702  } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down &&
22704  nk_textedit_click(edit, mouse_x, mouse_y, font, row_height);
22705  } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down &&
22706  (in->mouse.delta.x != 0.0f || in->mouse.delta.y != 0.0f)) {
22707  nk_textedit_drag(edit, mouse_x, mouse_y, font, row_height);
22708  cursor_follow = nk_true;
22709  } else if (is_hovered && in->mouse.buttons[NK_BUTTON_RIGHT].clicked &&
22711  nk_textedit_key(edit, NK_KEY_TEXT_WORD_LEFT, nk_false, font, row_height);
22712  nk_textedit_key(edit, NK_KEY_TEXT_WORD_RIGHT, nk_true, font, row_height);
22713  cursor_follow = nk_true;
22714  }
22715 
22716  {int i; /* keyboard input */
22717  int old_mode = edit->mode;
22718  for (i = 0; i < NK_KEY_MAX; ++i) {
22719  if (i == NK_KEY_ENTER || i == NK_KEY_TAB) continue; /* special case */
22720  if (nk_input_is_key_pressed(in, (enum nk_keys)i)) {
22721  nk_textedit_key(edit, (enum nk_keys)i, shift_mod, font, row_height);
22722  cursor_follow = nk_true;
22723  }
22724  }
22725  if (old_mode != edit->mode) {
22726  in->keyboard.text_len = 0;
22727  }}
22728 
22729  /* text input */
22730  edit->filter = filter;
22731  if (in->keyboard.text_len) {
22733  cursor_follow = nk_true;
22734  in->keyboard.text_len = 0;
22735  }
22736 
22737  /* enter key handler */
22739  cursor_follow = nk_true;
22740  if (flags & NK_EDIT_CTRL_ENTER_NEWLINE && shift_mod)
22741  nk_textedit_text(edit, "\n", 1);
22742  else if (flags & NK_EDIT_SIG_ENTER)
22743  ret |= NK_EDIT_COMMITED;
22744  else nk_textedit_text(edit, "\n", 1);
22745  }
22746 
22747  /* cut & copy handler */
22748  {int copy= nk_input_is_key_pressed(in, NK_KEY_COPY);
22749  int cut = nk_input_is_key_pressed(in, NK_KEY_CUT);
22750  if ((copy || cut) && (flags & NK_EDIT_CLIPBOARD))
22751  {
22752  int glyph_len;
22753  nk_rune unicode;
22754  const char *text;
22755  int b = edit->select_start;
22756  int e = edit->select_end;
22757 
22758  int begin = NK_MIN(b, e);
22759  int end = NK_MAX(b, e);
22760  text = nk_str_at_const(&edit->string, begin, &unicode, &glyph_len);
22761  if (edit->clip.copy)
22762  edit->clip.copy(edit->clip.userdata, text, end - begin);
22763  if (cut && !(flags & NK_EDIT_READ_ONLY)){
22764  nk_textedit_cut(edit);
22765  cursor_follow = nk_true;
22766  }
22767  }}
22768 
22769  /* paste handler */
22770  {int paste = nk_input_is_key_pressed(in, NK_KEY_PASTE);
22771  if (paste && (flags & NK_EDIT_CLIPBOARD) && edit->clip.paste) {
22772  edit->clip.paste(edit->clip.userdata, edit);
22773  cursor_follow = nk_true;
22774  }}
22775 
22776  /* tab handler */
22777  {int tab = nk_input_is_key_pressed(in, NK_KEY_TAB);
22778  if (tab && (flags & NK_EDIT_ALLOW_TAB)) {
22779  nk_textedit_text(edit, " ", 4);
22780  cursor_follow = nk_true;
22781  }}
22782  }
22783 
22784  /* set widget state */
22785  if (edit->active)
22786  *state = NK_WIDGET_STATE_ACTIVE;
22787  else nk_widget_state_reset(state);
22788 
22789  if (is_hovered)
22790  *state |= NK_WIDGET_STATE_HOVERED;
22791 
22792  /* DRAW EDIT */
22793  {const char *text = nk_str_get_const(&edit->string);
22794  int len = nk_str_len_char(&edit->string);
22795 
22796  {/* select background colors/images */
22797  const struct nk_style_item *background;
22798  if (*state & NK_WIDGET_STATE_ACTIVED)
22799  background = &style->active;
22800  else if (*state & NK_WIDGET_STATE_HOVER)
22801  background = &style->hover;
22802  else background = &style->normal;
22803 
22804  /* draw background frame */
22805  if (background->type == NK_STYLE_ITEM_COLOR) {
22806  nk_stroke_rect(out, bounds, style->rounding, style->border, style->border_color);
22807  nk_fill_rect(out, bounds, style->rounding, background->data.color);
22808  } else nk_draw_image(out, bounds, &background->data.image, nk_white);}
22809 
22810  area.w = NK_MAX(0, area.w - style->cursor_size);
22811  if (edit->active)
22812  {
22813  int total_lines = 1;
22814  struct nk_vec2 text_size = nk_vec2(0,0);
22815 
22816  /* text pointer positions */
22817  const char *cursor_ptr = 0;
22818  const char *select_begin_ptr = 0;
22819  const char *select_end_ptr = 0;
22820 
22821  /* 2D pixel positions */
22822  struct nk_vec2 cursor_pos = nk_vec2(0,0);
22823  struct nk_vec2 selection_offset_start = nk_vec2(0,0);
22824  struct nk_vec2 selection_offset_end = nk_vec2(0,0);
22825 
22826  int selection_begin = NK_MIN(edit->select_start, edit->select_end);
22827  int selection_end = NK_MAX(edit->select_start, edit->select_end);
22828 
22829  /* calculate total line count + total space + cursor/selection position */
22830  float line_width = 0.0f;
22831  if (text && len)
22832  {
22833  /* utf8 encoding */
22834  float glyph_width;
22835  int glyph_len = 0;
22836  nk_rune unicode = 0;
22837  int text_len = 0;
22838  int glyphs = 0;
22839  int row_begin = 0;
22840 
22841  glyph_len = nk_utf_decode(text, &unicode, len);
22842  glyph_width = font->width(font->userdata, font->height, text, glyph_len);
22843  line_width = 0;
22844 
22845  /* iterate all lines */
22846  while ((text_len < len) && glyph_len)
22847  {
22848  /* set cursor 2D position and line */
22849  if (!cursor_ptr && glyphs == edit->cursor)
22850  {
22851  int glyph_offset;
22852  struct nk_vec2 out_offset;
22853  struct nk_vec2 row_size;
22854  const char *remaining;
22855 
22856  /* calculate 2d position */
22857  cursor_pos.y = (float)(total_lines-1) * row_height;
22858  row_size = nk_text_calculate_text_bounds(font, text+row_begin,
22859  text_len-row_begin, row_height, &remaining,
22860  &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
22861  cursor_pos.x = row_size.x;
22862  cursor_ptr = text + text_len;
22863  }
22864 
22865  /* set start selection 2D position and line */
22866  if (!select_begin_ptr && edit->select_start != edit->select_end &&
22867  glyphs == selection_begin)
22868  {
22869  int glyph_offset;
22870  struct nk_vec2 out_offset;
22871  struct nk_vec2 row_size;
22872  const char *remaining;
22873 
22874  /* calculate 2d position */
22875  selection_offset_start.y = (float)(NK_MAX(total_lines-1,0)) * row_height;
22876  row_size = nk_text_calculate_text_bounds(font, text+row_begin,
22877  text_len-row_begin, row_height, &remaining,
22878  &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
22879  selection_offset_start.x = row_size.x;
22880  select_begin_ptr = text + text_len;
22881  }
22882 
22883  /* set end selection 2D position and line */
22884  if (!select_end_ptr && edit->select_start != edit->select_end &&
22885  glyphs == selection_end)
22886  {
22887  int glyph_offset;
22888  struct nk_vec2 out_offset;
22889  struct nk_vec2 row_size;
22890  const char *remaining;
22891 
22892  /* calculate 2d position */
22893  selection_offset_end.y = (float)(total_lines-1) * row_height;
22894  row_size = nk_text_calculate_text_bounds(font, text+row_begin,
22895  text_len-row_begin, row_height, &remaining,
22896  &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
22897  selection_offset_end.x = row_size.x;
22898  select_end_ptr = text + text_len;
22899  }
22900  if (unicode == '\n') {
22901  text_size.x = NK_MAX(text_size.x, line_width);
22902  total_lines++;
22903  line_width = 0;
22904  text_len++;
22905  glyphs++;
22906  row_begin = text_len;
22907  glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len);
22908  glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len);
22909  continue;
22910  }
22911 
22912  glyphs++;
22913  text_len += glyph_len;
22914  line_width += (float)glyph_width;
22915 
22916  glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len);
22917  glyph_width = font->width(font->userdata, font->height,
22918  text+text_len, glyph_len);
22919  continue;
22920  }
22921  text_size.y = (float)total_lines * row_height;
22922 
22923  /* handle case when cursor is at end of text buffer */
22924  if (!cursor_ptr && edit->cursor == edit->string.len) {
22925  cursor_pos.x = line_width;
22926  cursor_pos.y = text_size.y - row_height;
22927  }
22928  }
22929  {
22930  /* scrollbar */
22931  if (cursor_follow)
22932  {
22933  /* update scrollbar to follow cursor */
22934  if (!(flags & NK_EDIT_NO_HORIZONTAL_SCROLL)) {
22935  /* horizontal scroll */
22936  const float scroll_increment = area.w * 0.25f;
22937  if (cursor_pos.x < edit->scrollbar.x)
22938  edit->scrollbar.x = (float)(int)NK_MAX(0.0f, cursor_pos.x - scroll_increment);
22939  if (cursor_pos.x >= edit->scrollbar.x + area.w)
22940  edit->scrollbar.x = (float)(int)NK_MAX(0.0f, edit->scrollbar.x + scroll_increment);
22941  } else edit->scrollbar.x = 0;
22942 
22943  if (flags & NK_EDIT_MULTILINE) {
22944  /* vertical scroll */
22945  if (cursor_pos.y < edit->scrollbar.y)
22946  edit->scrollbar.y = NK_MAX(0.0f, cursor_pos.y - row_height);
22947  if (cursor_pos.y >= edit->scrollbar.y + area.h)
22948  edit->scrollbar.y = edit->scrollbar.y + row_height;
22949  } else edit->scrollbar.y = 0;
22950  }
22951 
22952  /* scrollbar widget */
22953  if (flags & NK_EDIT_MULTILINE)
22954  {
22955  nk_flags ws;
22956  struct nk_rect scroll;
22957  float scroll_target;
22958  float scroll_offset;
22959  float scroll_step;
22960  float scroll_inc;
22961 
22962  scroll = area;
22963  scroll.x = (bounds.x + bounds.w - style->border) - style->scrollbar_size.x;
22964  scroll.w = style->scrollbar_size.x;
22965 
22966  scroll_offset = edit->scrollbar.y;
22967  scroll_step = scroll.h * 0.10f;
22968  scroll_inc = scroll.h * 0.01f;
22969  scroll_target = text_size.y;
22970  edit->scrollbar.y = nk_do_scrollbarv(&ws, out, scroll, 0,
22971  scroll_offset, scroll_target, scroll_step, scroll_inc,
22972  &style->scrollbar, in, font);
22973  }
22974  }
22975 
22976  /* draw text */
22977  {struct nk_color background_color;
22978  struct nk_color text_color;
22979  struct nk_color sel_background_color;
22980  struct nk_color sel_text_color;
22981  struct nk_color cursor_color;
22982  struct nk_color cursor_text_color;
22983  const struct nk_style_item *background;
22984  nk_push_scissor(out, clip);
22985 
22986  /* select correct colors to draw */
22987  if (*state & NK_WIDGET_STATE_ACTIVED) {
22988  background = &style->active;
22989  text_color = style->text_active;
22990  sel_text_color = style->selected_text_hover;
22991  sel_background_color = style->selected_hover;
22992  cursor_color = style->cursor_hover;
22993  cursor_text_color = style->cursor_text_hover;
22994  } else if (*state & NK_WIDGET_STATE_HOVER) {
22995  background = &style->hover;
22996  text_color = style->text_hover;
22997  sel_text_color = style->selected_text_hover;
22998  sel_background_color = style->selected_hover;
22999  cursor_text_color = style->cursor_text_hover;
23000  cursor_color = style->cursor_hover;
23001  } else {
23002  background = &style->normal;
23003  text_color = style->text_normal;
23004  sel_text_color = style->selected_text_normal;
23005  sel_background_color = style->selected_normal;
23006  cursor_color = style->cursor_normal;
23007  cursor_text_color = style->cursor_text_normal;
23008  }
23009  if (background->type == NK_STYLE_ITEM_IMAGE)
23010  background_color = nk_rgba(0,0,0,0);
23011  else background_color = background->data.color;
23012 
23013 
23014  if (edit->select_start == edit->select_end) {
23015  /* no selection so just draw the complete text */
23016  const char *begin = nk_str_get_const(&edit->string);
23017  int l = nk_str_len_char(&edit->string);
23018  nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
23019  area.y - edit->scrollbar.y, 0, begin, l, row_height, font,
23020  background_color, text_color, nk_false);
23021  } else {
23022  /* edit has selection so draw 1-3 text chunks */
23023  if (edit->select_start != edit->select_end && selection_begin > 0){
23024  /* draw unselected text before selection */
23025  const char *begin = nk_str_get_const(&edit->string);
23026  NK_ASSERT(select_begin_ptr);
23027  nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
23028  area.y - edit->scrollbar.y, 0, begin, (int)(select_begin_ptr - begin),
23029  row_height, font, background_color, text_color, nk_false);
23030  }
23031  if (edit->select_start != edit->select_end) {
23032  /* draw selected text */
23033  NK_ASSERT(select_begin_ptr);
23034  if (!select_end_ptr) {
23035  const char *begin = nk_str_get_const(&edit->string);
23036  select_end_ptr = begin + nk_str_len_char(&edit->string);
23037  }
23038  nk_edit_draw_text(out, style,
23039  area.x - edit->scrollbar.x,
23040  area.y + selection_offset_start.y - edit->scrollbar.y,
23041  selection_offset_start.x,
23042  select_begin_ptr, (int)(select_end_ptr - select_begin_ptr),
23043  row_height, font, sel_background_color, sel_text_color, nk_true);
23044  }
23045  if ((edit->select_start != edit->select_end &&
23046  selection_end < edit->string.len))
23047  {
23048  /* draw unselected text after selected text */
23049  const char *begin = select_end_ptr;
23050  const char *end = nk_str_get_const(&edit->string) +
23051  nk_str_len_char(&edit->string);
23052  NK_ASSERT(select_end_ptr);
23053  nk_edit_draw_text(out, style,
23054  area.x - edit->scrollbar.x,
23055  area.y + selection_offset_end.y - edit->scrollbar.y,
23056  selection_offset_end.x,
23057  begin, (int)(end - begin), row_height, font,
23058  background_color, text_color, nk_true);
23059  }
23060  }
23061 
23062  /* cursor */
23063  if (edit->select_start == edit->select_end)
23064  {
23065  if (edit->cursor >= nk_str_len(&edit->string) ||
23066  (cursor_ptr && *cursor_ptr == '\n')) {
23067  /* draw cursor at end of line */
23068  struct nk_rect cursor;
23069  cursor.w = style->cursor_size;
23070  cursor.h = font->height;
23071  cursor.x = area.x + cursor_pos.x - edit->scrollbar.x;
23072  cursor.y = area.y + cursor_pos.y + row_height/2.0f - cursor.h/2.0f;
23073  cursor.y -= edit->scrollbar.y;
23074  nk_fill_rect(out, cursor, 0, cursor_color);
23075  } else {
23076  /* draw cursor inside text */
23077  int glyph_len;
23078  struct nk_rect label;
23079  struct nk_text txt;
23080 
23081  nk_rune unicode;
23082  NK_ASSERT(cursor_ptr);
23083  glyph_len = nk_utf_decode(cursor_ptr, &unicode, 4);
23084 
23085  label.x = area.x + cursor_pos.x - edit->scrollbar.x;
23086  label.y = area.y + cursor_pos.y - edit->scrollbar.y;
23087  label.w = font->width(font->userdata, font->height, cursor_ptr, glyph_len);
23088  label.h = row_height;
23089 
23090  txt.padding = nk_vec2(0,0);
23091  txt.background = cursor_color;;
23092  txt.text = cursor_text_color;
23093  nk_fill_rect(out, label, 0, cursor_color);
23094  nk_widget_text(out, label, cursor_ptr, glyph_len, &txt, NK_TEXT_LEFT, font);
23095  }
23096  }}
23097  } else {
23098  /* not active so just draw text */
23099  int l = nk_str_len_char(&edit->string);
23100  const char *begin = nk_str_get_const(&edit->string);
23101 
23102  const struct nk_style_item *background;
23103  struct nk_color background_color;
23104  struct nk_color text_color;
23105  nk_push_scissor(out, clip);
23106  if (*state & NK_WIDGET_STATE_ACTIVED) {
23107  background = &style->active;
23108  text_color = style->text_active;
23109  } else if (*state & NK_WIDGET_STATE_HOVER) {
23110  background = &style->hover;
23111  text_color = style->text_hover;
23112  } else {
23113  background = &style->normal;
23114  text_color = style->text_normal;
23115  }
23116  if (background->type == NK_STYLE_ITEM_IMAGE)
23117  background_color = nk_rgba(0,0,0,0);
23118  else background_color = background->data.color;
23119  nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
23120  area.y - edit->scrollbar.y, 0, begin, l, row_height, font,
23121  background_color, text_color, nk_false);
23122  }
23123  nk_push_scissor(out, old_clip);}
23124  return ret;
23125 }
23126 NK_API void
23127 nk_edit_focus(struct nk_context *ctx, nk_flags flags)
23128 {
23129  nk_hash hash;
23130  struct nk_window *win;
23131 
23132  NK_ASSERT(ctx);
23133  NK_ASSERT(ctx->current);
23134  if (!ctx || !ctx->current) return;
23135 
23136  win = ctx->current;
23137  hash = win->edit.seq;
23138  win->edit.active = nk_true;
23139  win->edit.name = hash;
23142 }
23143 NK_API void
23144 nk_edit_unfocus(struct nk_context *ctx)
23145 {
23146  struct nk_window *win;
23147  NK_ASSERT(ctx);
23148  NK_ASSERT(ctx->current);
23149  if (!ctx || !ctx->current) return;
23150 
23151  win = ctx->current;
23152  win->edit.active = nk_false;
23153  win->edit.name = 0;
23154 }
23157  char *memory, int *len, int max, nk_plugin_filter filter)
23158 {
23159  nk_hash hash;
23160  nk_flags state;
23161  struct nk_text_edit *edit;
23162  struct nk_window *win;
23163 
23164  NK_ASSERT(ctx);
23165  NK_ASSERT(memory);
23166  NK_ASSERT(len);
23167  if (!ctx || !memory || !len)
23168  return 0;
23169 
23170  filter = (!filter) ? nk_filter_default: filter;
23171  win = ctx->current;
23172  hash = win->edit.seq;
23173  edit = &ctx->text_edit;
23174  nk_textedit_clear_state(&ctx->text_edit, (flags & NK_EDIT_MULTILINE)?
23176 
23177  if (win->edit.active && hash == win->edit.name) {
23178  if (flags & NK_EDIT_NO_CURSOR)
23179  edit->cursor = nk_utf_len(memory, *len);
23180  else edit->cursor = win->edit.cursor;
23181  if (!(flags & NK_EDIT_SELECTABLE)) {
23182  edit->select_start = win->edit.cursor;
23183  edit->select_end = win->edit.cursor;
23184  } else {
23185  edit->select_start = win->edit.sel_start;
23186  edit->select_end = win->edit.sel_end;
23187  }
23188  edit->mode = win->edit.mode;
23189  edit->scrollbar.x = (float)win->edit.scrollbar.x;
23190  edit->scrollbar.y = (float)win->edit.scrollbar.y;
23191  edit->active = nk_true;
23192  } else edit->active = nk_false;
23193 
23194  max = NK_MAX(1, max);
23195  *len = NK_MIN(*len, max-1);
23196  nk_str_init_fixed(&edit->string, memory, (nk_size)max);
23197  edit->string.buffer.allocated = (nk_size)*len;
23198  edit->string.len = nk_utf_len(memory, *len);
23199  state = nk_edit_buffer(ctx, flags, edit, filter);
23200  *len = (int)edit->string.buffer.allocated;
23201 
23202  if (edit->active) {
23203  win->edit.cursor = edit->cursor;
23204  win->edit.sel_start = edit->select_start;
23205  win->edit.sel_end = edit->select_end;
23206  win->edit.mode = edit->mode;
23207  win->edit.scrollbar.x = (nk_uint)edit->scrollbar.x;
23208  win->edit.scrollbar.y = (nk_uint)edit->scrollbar.y;
23209  } return state;
23210 }
23213  struct nk_text_edit *edit, nk_plugin_filter filter)
23214 {
23215  struct nk_window *win;
23216  struct nk_style *style;
23217  struct nk_input *in;
23218 
23219  enum nk_widget_layout_states state;
23220  struct nk_rect bounds;
23221 
23222  nk_flags ret_flags = 0;
23223  unsigned char prev_state;
23224  nk_hash hash;
23225 
23226  /* make sure correct values */
23227  NK_ASSERT(ctx);
23228  NK_ASSERT(edit);
23229  NK_ASSERT(ctx->current);
23230  NK_ASSERT(ctx->current->layout);
23231  if (!ctx || !ctx->current || !ctx->current->layout)
23232  return 0;
23233 
23234  win = ctx->current;
23235  style = &ctx->style;
23236  state = nk_widget(&bounds, ctx);
23237  if (!state) return state;
23238  in = (win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23239 
23240  /* check if edit is currently hot item */
23241  hash = win->edit.seq++;
23242  if (win->edit.active && hash == win->edit.name) {
23243  if (flags & NK_EDIT_NO_CURSOR)
23244  edit->cursor = edit->string.len;
23245  if (!(flags & NK_EDIT_SELECTABLE)) {
23246  edit->select_start = edit->cursor;
23247  edit->select_end = edit->cursor;
23248  }
23249  if (flags & NK_EDIT_CLIPBOARD)
23250  edit->clip = ctx->clip;
23251  edit->active = (unsigned char)win->edit.active;
23252  } else edit->active = nk_false;
23253  edit->mode = win->edit.mode;
23254 
23255  filter = (!filter) ? nk_filter_default: filter;
23256  prev_state = (unsigned char)edit->active;
23257  in = (flags & NK_EDIT_READ_ONLY) ? 0: in;
23258  ret_flags = nk_do_edit(&ctx->last_widget_state, &win->buffer, bounds, flags,
23259  filter, edit, &style->edit, in, style->font);
23260 
23263  if (edit->active && prev_state != edit->active) {
23264  /* current edit is now hot */
23265  win->edit.active = nk_true;
23266  win->edit.name = hash;
23267  } else if (prev_state && !edit->active) {
23268  /* current edit is now cold */
23269  win->edit.active = nk_false;
23270  } return ret_flags;
23271 }
23274  char *buffer, int max, nk_plugin_filter filter)
23275 {
23276  nk_flags result;
23277  int len = nk_strlen(buffer);
23278  result = nk_edit_string(ctx, flags, buffer, &len, max, filter);
23279  buffer[NK_MIN(NK_MAX(max-1,0), len)] = '\0';
23280  return result;
23281 }
23282 
23283 
23284 
23285 
23286 
23287 /* ===============================================================
23288  *
23289  * PROPERTY
23290  *
23291  * ===============================================================*/
23292 NK_LIB void
23293 nk_drag_behavior(nk_flags *state, const struct nk_input *in,
23294  struct nk_rect drag, struct nk_property_variant *variant,
23295  float inc_per_pixel)
23296 {
23297  int left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
23298  int left_mouse_click_in_cursor = in &&
23300 
23301  nk_widget_state_reset(state);
23302  if (nk_input_is_mouse_hovering_rect(in, drag))
23303  *state = NK_WIDGET_STATE_HOVERED;
23304 
23305  if (left_mouse_down && left_mouse_click_in_cursor) {
23306  float delta, pixels;
23307  pixels = in->mouse.delta.x;
23308  delta = pixels * inc_per_pixel;
23309  switch (variant->kind) {
23310  default: break;
23311  case NK_PROPERTY_INT:
23312  variant->value.i = variant->value.i + (int)delta;
23313  variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
23314  break;
23315  case NK_PROPERTY_FLOAT:
23316  variant->value.f = variant->value.f + (float)delta;
23317  variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
23318  break;
23319  case NK_PROPERTY_DOUBLE:
23320  variant->value.d = variant->value.d + (double)delta;
23321  variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
23322  break;
23323  }
23324  *state = NK_WIDGET_STATE_ACTIVE;
23325  }
23327  *state |= NK_WIDGET_STATE_ENTERED;
23328  else if (nk_input_is_mouse_prev_hovering_rect(in, drag))
23329  *state |= NK_WIDGET_STATE_LEFT;
23330 }
23331 NK_LIB void
23332 nk_property_behavior(nk_flags *ws, const struct nk_input *in,
23333  struct nk_rect property, struct nk_rect label, struct nk_rect edit,
23334  struct nk_rect empty, int *state, struct nk_property_variant *variant,
23335  float inc_per_pixel)
23336 {
23337  if (in && *state == NK_PROPERTY_DEFAULT) {
23338  if (nk_button_behavior(ws, edit, in, NK_BUTTON_DEFAULT))
23339  *state = NK_PROPERTY_EDIT;
23341  *state = NK_PROPERTY_DRAG;
23343  *state = NK_PROPERTY_DRAG;
23344  }
23345  if (*state == NK_PROPERTY_DRAG) {
23346  nk_drag_behavior(ws, in, property, variant, inc_per_pixel);
23347  if (!(*ws & NK_WIDGET_STATE_ACTIVED)) *state = NK_PROPERTY_DEFAULT;
23348  }
23349 }
23350 NK_LIB void
23351 nk_draw_property(struct nk_command_buffer *out, const struct nk_style_property *style,
23352  const struct nk_rect *bounds, const struct nk_rect *label, nk_flags state,
23353  const char *name, int len, const struct nk_user_font *font)
23354 {
23355  struct nk_text text;
23356  const struct nk_style_item *background;
23357 
23358  /* select correct background and text color */
23359  if (state & NK_WIDGET_STATE_ACTIVED) {
23360  background = &style->active;
23361  text.text = style->label_active;
23362  } else if (state & NK_WIDGET_STATE_HOVER) {
23363  background = &style->hover;
23364  text.text = style->label_hover;
23365  } else {
23366  background = &style->normal;
23367  text.text = style->label_normal;
23368  }
23369 
23370  /* draw background */
23371  if (background->type == NK_STYLE_ITEM_IMAGE) {
23372  nk_draw_image(out, *bounds, &background->data.image, nk_white);
23373  text.background = nk_rgba(0,0,0,0);
23374  } else {
23375  text.background = background->data.color;
23376  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
23377  nk_stroke_rect(out, *bounds, style->rounding, style->border, background->data.color);
23378  }
23379 
23380  /* draw label */
23381  text.padding = nk_vec2(0,0);
23382  nk_widget_text(out, *label, name, len, &text, NK_TEXT_CENTERED, font);
23383 }
23384 NK_LIB void
23385 nk_do_property(nk_flags *ws,
23386  struct nk_command_buffer *out, struct nk_rect property,
23387  const char *name, struct nk_property_variant *variant,
23388  float inc_per_pixel, char *buffer, int *len,
23389  int *state, int *cursor, int *select_begin, int *select_end,
23390  const struct nk_style_property *style,
23391  enum nk_property_filter filter, struct nk_input *in,
23392  const struct nk_user_font *font, struct nk_text_edit *text_edit,
23393  enum nk_button_behavior behavior)
23394 {
23395  const nk_plugin_filter filters[] = {
23398  };
23399  int active, old;
23400  int num_len, name_len;
23401  char string[NK_MAX_NUMBER_BUFFER];
23402  float size;
23403 
23404  char *dst = 0;
23405  int *length;
23406 
23407  struct nk_rect left;
23408  struct nk_rect right;
23409  struct nk_rect label;
23410  struct nk_rect edit;
23411  struct nk_rect empty;
23412 
23413  /* left decrement button */
23414  left.h = font->height/2;
23415  left.w = left.h;
23416  left.x = property.x + style->border + style->padding.x;
23417  left.y = property.y + style->border + property.h/2.0f - left.h/2;
23418 
23419  /* text label */
23420  name_len = nk_strlen(name);
23421  size = font->width(font->userdata, font->height, name, name_len);
23422  label.x = left.x + left.w + style->padding.x;
23423  label.w = (float)size + 2 * style->padding.x;
23424  label.y = property.y + style->border + style->padding.y;
23425  label.h = property.h - (2 * style->border + 2 * style->padding.y);
23426 
23427  /* right increment button */
23428  right.y = left.y;
23429  right.w = left.w;
23430  right.h = left.h;
23431  right.x = property.x + property.w - (right.w + style->padding.x);
23432 
23433  /* edit */
23434  if (*state == NK_PROPERTY_EDIT) {
23435  size = font->width(font->userdata, font->height, buffer, *len);
23436  size += style->edit.cursor_size;
23437  length = len;
23438  dst = buffer;
23439  } else {
23440  switch (variant->kind) {
23441  default: break;
23442  case NK_PROPERTY_INT:
23443  nk_itoa(string, variant->value.i);
23444  num_len = nk_strlen(string);
23445  break;
23446  case NK_PROPERTY_FLOAT:
23447  NK_DTOA(string, (double)variant->value.f);
23448  num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
23449  break;
23450  case NK_PROPERTY_DOUBLE:
23451  NK_DTOA(string, variant->value.d);
23452  num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
23453  break;
23454  }
23455  size = font->width(font->userdata, font->height, string, num_len);
23456  dst = string;
23457  length = &num_len;
23458  }
23459 
23460  edit.w = (float)size + 2 * style->padding.x;
23461  edit.w = NK_MIN(edit.w, right.x - (label.x + label.w));
23462  edit.x = right.x - (edit.w + style->padding.x);
23463  edit.y = property.y + style->border;
23464  edit.h = property.h - (2 * style->border);
23465 
23466  /* empty left space activator */
23467  empty.w = edit.x - (label.x + label.w);
23468  empty.x = label.x + label.w;
23469  empty.y = property.y;
23470  empty.h = property.h;
23471 
23472  /* update property */
23473  old = (*state == NK_PROPERTY_EDIT);
23474  nk_property_behavior(ws, in, property, label, edit, empty, state, variant, inc_per_pixel);
23475 
23476  /* draw property */
23477  if (style->draw_begin) style->draw_begin(out, style->userdata);
23478  nk_draw_property(out, style, &property, &label, *ws, name, name_len, font);
23479  if (style->draw_end) style->draw_end(out, style->userdata);
23480 
23481  /* execute right button */
23482  if (nk_do_button_symbol(ws, out, left, style->sym_left, behavior, &style->dec_button, in, font)) {
23483  switch (variant->kind) {
23484  default: break;
23485  case NK_PROPERTY_INT:
23486  variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i - variant->step.i, variant->max_value.i); break;
23487  case NK_PROPERTY_FLOAT:
23488  variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f - variant->step.f, variant->max_value.f); break;
23489  case NK_PROPERTY_DOUBLE:
23490  variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d - variant->step.d, variant->max_value.d); break;
23491  }
23492  }
23493  /* execute left button */
23494  if (nk_do_button_symbol(ws, out, right, style->sym_right, behavior, &style->inc_button, in, font)) {
23495  switch (variant->kind) {
23496  default: break;
23497  case NK_PROPERTY_INT:
23498  variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i + variant->step.i, variant->max_value.i); break;
23499  case NK_PROPERTY_FLOAT:
23500  variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f + variant->step.f, variant->max_value.f); break;
23501  case NK_PROPERTY_DOUBLE:
23502  variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d + variant->step.d, variant->max_value.d); break;
23503  }
23504  }
23505  if (old != NK_PROPERTY_EDIT && (*state == NK_PROPERTY_EDIT)) {
23506  /* property has been activated so setup buffer */
23507  NK_MEMCPY(buffer, dst, (nk_size)*length);
23508  *cursor = nk_utf_len(buffer, *length);
23509  *len = *length;
23510  length = len;
23511  dst = buffer;
23512  active = 0;
23513  } else active = (*state == NK_PROPERTY_EDIT);
23514 
23515  /* execute and run text edit field */
23516  nk_textedit_clear_state(text_edit, NK_TEXT_EDIT_SINGLE_LINE, filters[filter]);
23517  text_edit->active = (unsigned char)active;
23518  text_edit->string.len = *length;
23519  text_edit->cursor = NK_CLAMP(0, *cursor, *length);
23520  text_edit->select_start = NK_CLAMP(0,*select_begin, *length);
23521  text_edit->select_end = NK_CLAMP(0,*select_end, *length);
23522  text_edit->string.buffer.allocated = (nk_size)*length;
23524  text_edit->string.buffer.memory.ptr = dst;
23525  text_edit->string.buffer.size = NK_MAX_NUMBER_BUFFER;
23526  text_edit->mode = NK_TEXT_EDIT_MODE_INSERT;
23527  nk_do_edit(ws, out, edit, NK_EDIT_FIELD|NK_EDIT_AUTO_SELECT,
23528  filters[filter], text_edit, &style->edit, (*state == NK_PROPERTY_EDIT) ? in: 0, font);
23529 
23530  *length = text_edit->string.len;
23531  *cursor = text_edit->cursor;
23532  *select_begin = text_edit->select_start;
23533  *select_end = text_edit->select_end;
23534  if (text_edit->active && nk_input_is_key_pressed(in, NK_KEY_ENTER))
23535  text_edit->active = nk_false;
23536 
23537  if (active && !text_edit->active) {
23538  /* property is now not active so convert edit text to value*/
23539  *state = NK_PROPERTY_DEFAULT;
23540  buffer[*len] = '\0';
23541  switch (variant->kind) {
23542  default: break;
23543  case NK_PROPERTY_INT:
23544  variant->value.i = nk_strtoi(buffer, 0);
23545  variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
23546  break;
23547  case NK_PROPERTY_FLOAT:
23548  nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
23549  variant->value.f = nk_strtof(buffer, 0);
23550  variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
23551  break;
23552  case NK_PROPERTY_DOUBLE:
23553  nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
23554  variant->value.d = nk_strtod(buffer, 0);
23555  variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
23556  break;
23557  }
23558  }
23559 }
23560 NK_LIB struct nk_property_variant
23561 nk_property_variant_int(int value, int min_value, int max_value, int step)
23562 {
23563  struct nk_property_variant result;
23564  result.kind = NK_PROPERTY_INT;
23565  result.value.i = value;
23566  result.min_value.i = min_value;
23567  result.max_value.i = max_value;
23568  result.step.i = step;
23569  return result;
23570 }
23571 NK_LIB struct nk_property_variant
23572 nk_property_variant_float(float value, float min_value, float max_value, float step)
23573 {
23574  struct nk_property_variant result;
23575  result.kind = NK_PROPERTY_FLOAT;
23576  result.value.f = value;
23577  result.min_value.f = min_value;
23578  result.max_value.f = max_value;
23579  result.step.f = step;
23580  return result;
23581 }
23582 NK_LIB struct nk_property_variant
23583 nk_property_variant_double(double value, double min_value, double max_value,
23584  double step)
23585 {
23586  struct nk_property_variant result;
23587  result.kind = NK_PROPERTY_DOUBLE;
23588  result.value.d = value;
23589  result.min_value.d = min_value;
23590  result.max_value.d = max_value;
23591  result.step.d = step;
23592  return result;
23593 }
23594 NK_LIB void
23595 nk_property(struct nk_context *ctx, const char *name, struct nk_property_variant *variant,
23596  float inc_per_pixel, const enum nk_property_filter filter)
23597 {
23598  struct nk_window *win;
23599  struct nk_panel *layout;
23600  struct nk_input *in;
23601  const struct nk_style *style;
23602 
23603  struct nk_rect bounds;
23604  enum nk_widget_layout_states s;
23605 
23606  int *state = 0;
23607  nk_hash hash = 0;
23608  char *buffer = 0;
23609  int *len = 0;
23610  int *cursor = 0;
23611  int *select_begin = 0;
23612  int *select_end = 0;
23613  int old_state;
23614 
23615  char dummy_buffer[NK_MAX_NUMBER_BUFFER];
23616  int dummy_state = NK_PROPERTY_DEFAULT;
23617  int dummy_length = 0;
23618  int dummy_cursor = 0;
23619  int dummy_select_begin = 0;
23620  int dummy_select_end = 0;
23621 
23622  NK_ASSERT(ctx);
23623  NK_ASSERT(ctx->current);
23624  NK_ASSERT(ctx->current->layout);
23625  if (!ctx || !ctx->current || !ctx->current->layout)
23626  return;
23627 
23628  win = ctx->current;
23629  layout = win->layout;
23630  style = &ctx->style;
23631  s = nk_widget(&bounds, ctx);
23632  if (!s) return;
23633 
23634  /* calculate hash from name */
23635  if (name[0] == '#') {
23636  hash = nk_murmur_hash(name, (int)nk_strlen(name), win->property.seq++);
23637  name++; /* special number hash */
23638  } else hash = nk_murmur_hash(name, (int)nk_strlen(name), 42);
23639 
23640  /* check if property is currently hot item */
23641  if (win->property.active && hash == win->property.name) {
23642  buffer = win->property.buffer;
23643  len = &win->property.length;
23644  cursor = &win->property.cursor;
23645  state = &win->property.state;
23646  select_begin = &win->property.select_start;
23647  select_end = &win->property.select_end;
23648  } else {
23649  buffer = dummy_buffer;
23650  len = &dummy_length;
23651  cursor = &dummy_cursor;
23652  state = &dummy_state;
23653  select_begin = &dummy_select_begin;
23654  select_end = &dummy_select_end;
23655  }
23656 
23657  /* execute property widget */
23658  old_state = *state;
23659  ctx->text_edit.clip = ctx->clip;
23660  in = ((s == NK_WIDGET_ROM && !win->property.active) ||
23661  layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23662  nk_do_property(&ctx->last_widget_state, &win->buffer, bounds, name,
23663  variant, inc_per_pixel, buffer, len, state, cursor, select_begin,
23664  select_end, &style->property, filter, in, style->font, &ctx->text_edit,
23665  ctx->button_behavior);
23666 
23667  if (in && *state != NK_PROPERTY_DEFAULT && !win->property.active) {
23668  /* current property is now hot */
23669  win->property.active = 1;
23670  NK_MEMCPY(win->property.buffer, buffer, (nk_size)*len);
23671  win->property.length = *len;
23672  win->property.cursor = *cursor;
23673  win->property.state = *state;
23674  win->property.name = hash;
23675  win->property.select_start = *select_begin;
23676  win->property.select_end = *select_end;
23677  if (*state == NK_PROPERTY_DRAG) {
23678  ctx->input.mouse.grab = nk_true;
23679  ctx->input.mouse.grabbed = nk_true;
23680  }
23681  }
23682  /* check if previously active property is now inactive */
23683  if (*state == NK_PROPERTY_DEFAULT && old_state != NK_PROPERTY_DEFAULT) {
23684  if (old_state == NK_PROPERTY_DRAG) {
23685  ctx->input.mouse.grab = nk_false;
23686  ctx->input.mouse.grabbed = nk_false;
23687  ctx->input.mouse.ungrab = nk_true;
23688  }
23689  win->property.select_start = 0;
23690  win->property.select_end = 0;
23691  win->property.active = 0;
23692  }
23693 }
23694 NK_API void
23695 nk_property_int(struct nk_context *ctx, const char *name,
23696  int min, int *val, int max, int step, float inc_per_pixel)
23697 {
23698  struct nk_property_variant variant;
23699  NK_ASSERT(ctx);
23700  NK_ASSERT(name);
23701  NK_ASSERT(val);
23702 
23703  if (!ctx || !ctx->current || !name || !val) return;
23704  variant = nk_property_variant_int(*val, min, max, step);
23705  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT);
23706  *val = variant.value.i;
23707 }
23708 NK_API void
23709 nk_property_float(struct nk_context *ctx, const char *name,
23710  float min, float *val, float max, float step, float inc_per_pixel)
23711 {
23712  struct nk_property_variant variant;
23713  NK_ASSERT(ctx);
23714  NK_ASSERT(name);
23715  NK_ASSERT(val);
23716 
23717  if (!ctx || !ctx->current || !name || !val) return;
23718  variant = nk_property_variant_float(*val, min, max, step);
23719  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
23720  *val = variant.value.f;
23721 }
23722 NK_API void
23723 nk_property_double(struct nk_context *ctx, const char *name,
23724  double min, double *val, double max, double step, float inc_per_pixel)
23725 {
23726  struct nk_property_variant variant;
23727  NK_ASSERT(ctx);
23728  NK_ASSERT(name);
23729  NK_ASSERT(val);
23730 
23731  if (!ctx || !ctx->current || !name || !val) return;
23732  variant = nk_property_variant_double(*val, min, max, step);
23733  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
23734  *val = variant.value.d;
23735 }
23736 NK_API int
23737 nk_propertyi(struct nk_context *ctx, const char *name, int min, int val,
23738  int max, int step, float inc_per_pixel)
23739 {
23740  struct nk_property_variant variant;
23741  NK_ASSERT(ctx);
23742  NK_ASSERT(name);
23743 
23744  if (!ctx || !ctx->current || !name) return val;
23745  variant = nk_property_variant_int(val, min, max, step);
23746  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT);
23747  val = variant.value.i;
23748  return val;
23749 }
23750 NK_API float
23751 nk_propertyf(struct nk_context *ctx, const char *name, float min,
23752  float val, float max, float step, float inc_per_pixel)
23753 {
23754  struct nk_property_variant variant;
23755  NK_ASSERT(ctx);
23756  NK_ASSERT(name);
23757 
23758  if (!ctx || !ctx->current || !name) return val;
23759  variant = nk_property_variant_float(val, min, max, step);
23760  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
23761  val = variant.value.f;
23762  return val;
23763 }
23764 NK_API double
23765 nk_propertyd(struct nk_context *ctx, const char *name, double min,
23766  double val, double max, double step, float inc_per_pixel)
23767 {
23768  struct nk_property_variant variant;
23769  NK_ASSERT(ctx);
23770  NK_ASSERT(name);
23771 
23772  if (!ctx || !ctx->current || !name) return val;
23773  variant = nk_property_variant_double(val, min, max, step);
23774  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
23775  val = variant.value.d;
23776  return val;
23777 }
23778 
23779 
23780 
23781 
23782 
23783 /* ==============================================================
23784  *
23785  * CHART
23786  *
23787  * ===============================================================*/
23788 NK_API int
23789 nk_chart_begin_colored(struct nk_context *ctx, enum nk_chart_type type,
23790  struct nk_color color, struct nk_color highlight,
23791  int count, float min_value, float max_value)
23792 {
23793  struct nk_window *win;
23794  struct nk_chart *chart;
23795  const struct nk_style *config;
23796  const struct nk_style_chart *style;
23797 
23798  const struct nk_style_item *background;
23799  struct nk_rect bounds = {0, 0, 0, 0};
23800 
23801  NK_ASSERT(ctx);
23802  NK_ASSERT(ctx->current);
23803  NK_ASSERT(ctx->current->layout);
23804 
23805  if (!ctx || !ctx->current || !ctx->current->layout) return 0;
23806  if (!nk_widget(&bounds, ctx)) {
23807  chart = &ctx->current->layout->chart;
23808  nk_zero(chart, sizeof(*chart));
23809  return 0;
23810  }
23811 
23812  win = ctx->current;
23813  config = &ctx->style;
23814  chart = &win->layout->chart;
23815  style = &config->chart;
23816 
23817  /* setup basic generic chart */
23818  nk_zero(chart, sizeof(*chart));
23819  chart->x = bounds.x + style->padding.x;
23820  chart->y = bounds.y + style->padding.y;
23821  chart->w = bounds.w - 2 * style->padding.x;
23822  chart->h = bounds.h - 2 * style->padding.y;
23823  chart->w = NK_MAX(chart->w, 2 * style->padding.x);
23824  chart->h = NK_MAX(chart->h, 2 * style->padding.y);
23825 
23826  /* add first slot into chart */
23827  {struct nk_chart_slot *slot = &chart->slots[chart->slot++];
23828  slot->type = type;
23829  slot->count = count;
23830  slot->color = color;
23831  slot->highlight = highlight;
23832  slot->min = NK_MIN(min_value, max_value);
23833  slot->max = NK_MAX(min_value, max_value);
23834  slot->range = slot->max - slot->min;}
23835 
23836  /* draw chart background */
23837  background = &style->background;
23838  if (background->type == NK_STYLE_ITEM_IMAGE) {
23839  nk_draw_image(&win->buffer, bounds, &background->data.image, nk_white);
23840  } else {
23841  nk_fill_rect(&win->buffer, bounds, style->rounding, style->border_color);
23842  nk_fill_rect(&win->buffer, nk_shrink_rect(bounds, style->border),
23843  style->rounding, style->background.data.color);
23844  }
23845  return 1;
23846 }
23847 NK_API int
23848 nk_chart_begin(struct nk_context *ctx, const enum nk_chart_type type,
23849  int count, float min_value, float max_value)
23850 {
23851  return nk_chart_begin_colored(ctx, type, ctx->style.chart.color,
23852  ctx->style.chart.selected_color, count, min_value, max_value);
23853 }
23854 NK_API void
23855 nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type type,
23856  struct nk_color color, struct nk_color highlight,
23857  int count, float min_value, float max_value)
23858 {
23859  NK_ASSERT(ctx);
23860  NK_ASSERT(ctx->current);
23861  NK_ASSERT(ctx->current->layout);
23862  NK_ASSERT(ctx->current->layout->chart.slot < NK_CHART_MAX_SLOT);
23863  if (!ctx || !ctx->current || !ctx->current->layout) return;
23864  if (ctx->current->layout->chart.slot >= NK_CHART_MAX_SLOT) return;
23865 
23866  /* add another slot into the graph */
23867  {struct nk_chart *chart = &ctx->current->layout->chart;
23868  struct nk_chart_slot *slot = &chart->slots[chart->slot++];
23869  slot->type = type;
23870  slot->count = count;
23871  slot->color = color;
23872  slot->highlight = highlight;
23873  slot->min = NK_MIN(min_value, max_value);
23874  slot->max = NK_MAX(min_value, max_value);
23875  slot->range = slot->max - slot->min;}
23876 }
23877 NK_API void
23878 nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type type,
23879  int count, float min_value, float max_value)
23880 {
23882  ctx->style.chart.selected_color, count, min_value, max_value);
23883 }
23885 nk_chart_push_line(struct nk_context *ctx, struct nk_window *win,
23886  struct nk_chart *g, float value, int slot)
23887 {
23888  struct nk_panel *layout = win->layout;
23889  const struct nk_input *i = &ctx->input;
23890  struct nk_command_buffer *out = &win->buffer;
23891 
23892  nk_flags ret = 0;
23893  struct nk_vec2 cur;
23894  struct nk_rect bounds;
23895  struct nk_color color;
23896  float step;
23897  float range;
23898  float ratio;
23899 
23900  NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
23901  step = g->w / (float)g->slots[slot].count;
23902  range = g->slots[slot].max - g->slots[slot].min;
23903  ratio = (value - g->slots[slot].min) / range;
23904 
23905  if (g->slots[slot].index == 0) {
23906  /* first data point does not have a connection */
23907  g->slots[slot].last.x = g->x;
23908  g->slots[slot].last.y = (g->y + g->h) - ratio * (float)g->h;
23909 
23910  bounds.x = g->slots[slot].last.x - 2;
23911  bounds.y = g->slots[slot].last.y - 2;
23912  bounds.w = bounds.h = 4;
23913 
23914  color = g->slots[slot].color;
23915  if (!(layout->flags & NK_WINDOW_ROM) &&
23916  NK_INBOX(i->mouse.pos.x,i->mouse.pos.y, g->slots[slot].last.x-3, g->slots[slot].last.y-3, 6, 6)){
23917  ret = nk_input_is_mouse_hovering_rect(i, bounds) ? NK_CHART_HOVERING : 0;
23918  ret |= (i->mouse.buttons[NK_BUTTON_LEFT].down &&
23920  color = g->slots[slot].highlight;
23921  }
23922  nk_fill_rect(out, bounds, 0, color);
23923  g->slots[slot].index += 1;
23924  return ret;
23925  }
23926 
23927  /* draw a line between the last data point and the new one */
23928  color = g->slots[slot].color;
23929  cur.x = g->x + (float)(step * (float)g->slots[slot].index);
23930  cur.y = (g->y + g->h) - (ratio * (float)g->h);
23931  nk_stroke_line(out, g->slots[slot].last.x, g->slots[slot].last.y, cur.x, cur.y, 1.0f, color);
23932 
23933  bounds.x = cur.x - 3;
23934  bounds.y = cur.y - 3;
23935  bounds.w = bounds.h = 6;
23936 
23937  /* user selection of current data point */
23938  if (!(layout->flags & NK_WINDOW_ROM)) {
23939  if (nk_input_is_mouse_hovering_rect(i, bounds)) {
23940  ret = NK_CHART_HOVERING;
23941  ret |= (!i->mouse.buttons[NK_BUTTON_LEFT].down &&
23943  color = g->slots[slot].highlight;
23944  }
23945  }
23946  nk_fill_rect(out, nk_rect(cur.x - 2, cur.y - 2, 4, 4), 0, color);
23947 
23948  /* save current data point position */
23949  g->slots[slot].last.x = cur.x;
23950  g->slots[slot].last.y = cur.y;
23951  g->slots[slot].index += 1;
23952  return ret;
23953 }
23955 nk_chart_push_column(const struct nk_context *ctx, struct nk_window *win,
23956  struct nk_chart *chart, float value, int slot)
23957 {
23958  struct nk_command_buffer *out = &win->buffer;
23959  const struct nk_input *in = &ctx->input;
23960  struct nk_panel *layout = win->layout;
23961 
23962  float ratio;
23963  nk_flags ret = 0;
23964  struct nk_color color;
23965  struct nk_rect item = {0,0,0,0};
23966 
23967  NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
23968  if (chart->slots[slot].index >= chart->slots[slot].count)
23969  return nk_false;
23970  if (chart->slots[slot].count) {
23971  float padding = (float)(chart->slots[slot].count-1);
23972  item.w = (chart->w - padding) / (float)(chart->slots[slot].count);
23973  }
23974 
23975  /* calculate bounds of current bar chart entry */
23976  color = chart->slots[slot].color;;
23977  item.h = chart->h * NK_ABS((value/chart->slots[slot].range));
23978  if (value >= 0) {
23979  ratio = (value + NK_ABS(chart->slots[slot].min)) / NK_ABS(chart->slots[slot].range);
23980  item.y = (chart->y + chart->h) - chart->h * ratio;
23981  } else {
23982  ratio = (value - chart->slots[slot].max) / chart->slots[slot].range;
23983  item.y = chart->y + (chart->h * NK_ABS(ratio)) - item.h;
23984  }
23985  item.x = chart->x + ((float)chart->slots[slot].index * item.w);
23986  item.x = item.x + ((float)chart->slots[slot].index);
23987 
23988  /* user chart bar selection */
23989  if (!(layout->flags & NK_WINDOW_ROM) &&
23990  NK_INBOX(in->mouse.pos.x,in->mouse.pos.y,item.x,item.y,item.w,item.h)) {
23991  ret = NK_CHART_HOVERING;
23992  ret |= (!in->mouse.buttons[NK_BUTTON_LEFT].down &&
23994  color = chart->slots[slot].highlight;
23995  }
23996  nk_fill_rect(out, item, 0, color);
23997  chart->slots[slot].index += 1;
23998  return ret;
23999 }
24001 nk_chart_push_slot(struct nk_context *ctx, float value, int slot)
24002 {
24003  nk_flags flags;
24004  struct nk_window *win;
24005 
24006  NK_ASSERT(ctx);
24007  NK_ASSERT(ctx->current);
24008  NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
24009  NK_ASSERT(slot < ctx->current->layout->chart.slot);
24010  if (!ctx || !ctx->current || slot >= NK_CHART_MAX_SLOT) return nk_false;
24011  if (slot >= ctx->current->layout->chart.slot) return nk_false;
24012 
24013  win = ctx->current;
24014  if (win->layout->chart.slot < slot) return nk_false;
24015  switch (win->layout->chart.slots[slot].type) {
24016  case NK_CHART_LINES:
24017  flags = nk_chart_push_line(ctx, win, &win->layout->chart, value, slot); break;
24018  case NK_CHART_COLUMN:
24019  flags = nk_chart_push_column(ctx, win, &win->layout->chart, value, slot); break;
24020  default:
24021  case NK_CHART_MAX:
24022  flags = 0;
24023  }
24024  return flags;
24025 }
24027 nk_chart_push(struct nk_context *ctx, float value)
24028 {
24029  return nk_chart_push_slot(ctx, value, 0);
24030 }
24031 NK_API void
24032 nk_chart_end(struct nk_context *ctx)
24033 {
24034  struct nk_window *win;
24035  struct nk_chart *chart;
24036 
24037  NK_ASSERT(ctx);
24038  NK_ASSERT(ctx->current);
24039  if (!ctx || !ctx->current)
24040  return;
24041 
24042  win = ctx->current;
24043  chart = &win->layout->chart;
24044  NK_MEMSET(chart, 0, sizeof(*chart));
24045  return;
24046 }
24047 NK_API void
24048 nk_plot(struct nk_context *ctx, enum nk_chart_type type, const float *values,
24049  int count, int offset)
24050 {
24051  int i = 0;
24052  float min_value;
24053  float max_value;
24054 
24055  NK_ASSERT(ctx);
24056  NK_ASSERT(values);
24057  if (!ctx || !values || !count) return;
24058 
24059  min_value = values[offset];
24060  max_value = values[offset];
24061  for (i = 0; i < count; ++i) {
24062  min_value = NK_MIN(values[i + offset], min_value);
24063  max_value = NK_MAX(values[i + offset], max_value);
24064  }
24065 
24066  if (nk_chart_begin(ctx, type, count, min_value, max_value)) {
24067  for (i = 0; i < count; ++i)
24068  nk_chart_push(ctx, values[i + offset]);
24069  nk_chart_end(ctx);
24070  }
24071 }
24072 NK_API void
24073 nk_plot_function(struct nk_context *ctx, enum nk_chart_type type, void *userdata,
24074  float(*value_getter)(void* user, int index), int count, int offset)
24075 {
24076  int i = 0;
24077  float min_value;
24078  float max_value;
24079 
24080  NK_ASSERT(ctx);
24081  NK_ASSERT(value_getter);
24082  if (!ctx || !value_getter || !count) return;
24083 
24084  max_value = min_value = value_getter(userdata, offset);
24085  for (i = 0; i < count; ++i) {
24086  float value = value_getter(userdata, i + offset);
24087  min_value = NK_MIN(value, min_value);
24088  max_value = NK_MAX(value, max_value);
24089  }
24090 
24091  if (nk_chart_begin(ctx, type, count, min_value, max_value)) {
24092  for (i = 0; i < count; ++i)
24093  nk_chart_push(ctx, value_getter(userdata, i + offset));
24094  nk_chart_end(ctx);
24095  }
24096 }
24097 
24098 
24099 
24100 
24101 
24102 /* ==============================================================
24103  *
24104  * COLOR PICKER
24105  *
24106  * ===============================================================*/
24107 NK_LIB int
24108 nk_color_picker_behavior(nk_flags *state,
24109  const struct nk_rect *bounds, const struct nk_rect *matrix,
24110  const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar,
24111  struct nk_colorf *color, const struct nk_input *in)
24112 {
24113  float hsva[4];
24114  int value_changed = 0;
24115  int hsv_changed = 0;
24116 
24117  NK_ASSERT(state);
24118  NK_ASSERT(matrix);
24119  NK_ASSERT(hue_bar);
24120  NK_ASSERT(color);
24121 
24122  /* color matrix */
24123  nk_colorf_hsva_fv(hsva, *color);
24124  if (nk_button_behavior(state, *matrix, in, NK_BUTTON_REPEATER)) {
24125  hsva[1] = NK_SATURATE((in->mouse.pos.x - matrix->x) / (matrix->w-1));
24126  hsva[2] = 1.0f - NK_SATURATE((in->mouse.pos.y - matrix->y) / (matrix->h-1));
24127  value_changed = hsv_changed = 1;
24128  }
24129  /* hue bar */
24130  if (nk_button_behavior(state, *hue_bar, in, NK_BUTTON_REPEATER)) {
24131  hsva[0] = NK_SATURATE((in->mouse.pos.y - hue_bar->y) / (hue_bar->h-1));
24132  value_changed = hsv_changed = 1;
24133  }
24134  /* alpha bar */
24135  if (alpha_bar) {
24136  if (nk_button_behavior(state, *alpha_bar, in, NK_BUTTON_REPEATER)) {
24137  hsva[3] = 1.0f - NK_SATURATE((in->mouse.pos.y - alpha_bar->y) / (alpha_bar->h-1));
24138  value_changed = 1;
24139  }
24140  }
24141  nk_widget_state_reset(state);
24142  if (hsv_changed) {
24143  *color = nk_hsva_colorfv(hsva);
24144  *state = NK_WIDGET_STATE_ACTIVE;
24145  }
24146  if (value_changed) {
24147  color->a = hsva[3];
24148  *state = NK_WIDGET_STATE_ACTIVE;
24149  }
24150  /* set color picker widget state */
24151  if (nk_input_is_mouse_hovering_rect(in, *bounds))
24152  *state = NK_WIDGET_STATE_HOVERED;
24153  if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *bounds))
24154  *state |= NK_WIDGET_STATE_ENTERED;
24155  else if (nk_input_is_mouse_prev_hovering_rect(in, *bounds))
24156  *state |= NK_WIDGET_STATE_LEFT;
24157  return value_changed;
24158 }
24159 NK_LIB void
24160 nk_draw_color_picker(struct nk_command_buffer *o, const struct nk_rect *matrix,
24161  const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar,
24162  struct nk_colorf col)
24163 {
24164  NK_STORAGE const struct nk_color black = {0,0,0,255};
24165  NK_STORAGE const struct nk_color white = {255, 255, 255, 255};
24166  NK_STORAGE const struct nk_color black_trans = {0,0,0,0};
24167 
24168  const float crosshair_size = 7.0f;
24169  struct nk_color temp;
24170  float hsva[4];
24171  float line_y;
24172  int i;
24173 
24174  NK_ASSERT(o);
24175  NK_ASSERT(matrix);
24176  NK_ASSERT(hue_bar);
24177 
24178  /* draw hue bar */
24179  nk_colorf_hsva_fv(hsva, col);
24180  for (i = 0; i < 6; ++i) {
24181  NK_GLOBAL const struct nk_color hue_colors[] = {
24182  {255, 0, 0, 255}, {255,255,0,255}, {0,255,0,255}, {0, 255,255,255},
24183  {0,0,255,255}, {255, 0, 255, 255}, {255, 0, 0, 255}
24184  };
24186  nk_rect(hue_bar->x, hue_bar->y + (float)i * (hue_bar->h/6.0f) + 0.5f,
24187  hue_bar->w, (hue_bar->h/6.0f) + 0.5f), hue_colors[i], hue_colors[i],
24188  hue_colors[i+1], hue_colors[i+1]);
24189  }
24190  line_y = (float)(int)(hue_bar->y + hsva[0] * matrix->h + 0.5f);
24191  nk_stroke_line(o, hue_bar->x-1, line_y, hue_bar->x + hue_bar->w + 2,
24192  line_y, 1, nk_rgb(255,255,255));
24193 
24194  /* draw alpha bar */
24195  if (alpha_bar) {
24196  float alpha = NK_SATURATE(col.a);
24197  line_y = (float)(int)(alpha_bar->y + (1.0f - alpha) * matrix->h + 0.5f);
24198 
24199  nk_fill_rect_multi_color(o, *alpha_bar, white, white, black, black);
24200  nk_stroke_line(o, alpha_bar->x-1, line_y, alpha_bar->x + alpha_bar->w + 2,
24201  line_y, 1, nk_rgb(255,255,255));
24202  }
24203 
24204  /* draw color matrix */
24205  temp = nk_hsv_f(hsva[0], 1.0f, 1.0f);
24206  nk_fill_rect_multi_color(o, *matrix, white, temp, temp, white);
24207  nk_fill_rect_multi_color(o, *matrix, black_trans, black_trans, black, black);
24208 
24209  /* draw cross-hair */
24210  {struct nk_vec2 p; float S = hsva[1]; float V = hsva[2];
24211  p.x = (float)(int)(matrix->x + S * matrix->w);
24212  p.y = (float)(int)(matrix->y + (1.0f - V) * matrix->h);
24213  nk_stroke_line(o, p.x - crosshair_size, p.y, p.x-2, p.y, 1.0f, white);
24214  nk_stroke_line(o, p.x + crosshair_size + 1, p.y, p.x+3, p.y, 1.0f, white);
24215  nk_stroke_line(o, p.x, p.y + crosshair_size + 1, p.x, p.y+3, 1.0f, white);
24216  nk_stroke_line(o, p.x, p.y - crosshair_size, p.x, p.y-2, 1.0f, white);}
24217 }
24218 NK_LIB int
24219 nk_do_color_picker(nk_flags *state,
24220  struct nk_command_buffer *out, struct nk_colorf *col,
24221  enum nk_color_format fmt, struct nk_rect bounds,
24222  struct nk_vec2 padding, const struct nk_input *in,
24223  const struct nk_user_font *font)
24224 {
24225  int ret = 0;
24226  struct nk_rect matrix;
24227  struct nk_rect hue_bar;
24228  struct nk_rect alpha_bar;
24229  float bar_w;
24230 
24231  NK_ASSERT(out);
24232  NK_ASSERT(col);
24233  NK_ASSERT(state);
24234  NK_ASSERT(font);
24235  if (!out || !col || !state || !font)
24236  return ret;
24237 
24238  bar_w = font->height;
24239  bounds.x += padding.x;
24240  bounds.y += padding.x;
24241  bounds.w -= 2 * padding.x;
24242  bounds.h -= 2 * padding.y;
24243 
24244  matrix.x = bounds.x;
24245  matrix.y = bounds.y;
24246  matrix.h = bounds.h;
24247  matrix.w = bounds.w - (3 * padding.x + 2 * bar_w);
24248 
24249  hue_bar.w = bar_w;
24250  hue_bar.y = bounds.y;
24251  hue_bar.h = matrix.h;
24252  hue_bar.x = matrix.x + matrix.w + padding.x;
24253 
24254  alpha_bar.x = hue_bar.x + hue_bar.w + padding.x;
24255  alpha_bar.y = bounds.y;
24256  alpha_bar.w = bar_w;
24257  alpha_bar.h = matrix.h;
24258 
24259  ret = nk_color_picker_behavior(state, &bounds, &matrix, &hue_bar,
24260  (fmt == NK_RGBA) ? &alpha_bar:0, col, in);
24261  nk_draw_color_picker(out, &matrix, &hue_bar, (fmt == NK_RGBA) ? &alpha_bar:0, *col);
24262  return ret;
24263 }
24264 NK_API int
24265 nk_color_pick(struct nk_context * ctx, struct nk_colorf *color,
24266  enum nk_color_format fmt)
24267 {
24268  struct nk_window *win;
24269  struct nk_panel *layout;
24270  const struct nk_style *config;
24271  const struct nk_input *in;
24272 
24273  enum nk_widget_layout_states state;
24274  struct nk_rect bounds;
24275 
24276  NK_ASSERT(ctx);
24277  NK_ASSERT(color);
24278  NK_ASSERT(ctx->current);
24279  NK_ASSERT(ctx->current->layout);
24280  if (!ctx || !ctx->current || !ctx->current->layout || !color)
24281  return 0;
24282 
24283  win = ctx->current;
24284  config = &ctx->style;
24285  layout = win->layout;
24286  state = nk_widget(&bounds, ctx);
24287  if (!state) return 0;
24288  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
24289  return nk_do_color_picker(&ctx->last_widget_state, &win->buffer, color, fmt, bounds,
24290  nk_vec2(0,0), in, config->font);
24291 }
24292 NK_API struct nk_colorf
24293 nk_color_picker(struct nk_context *ctx, struct nk_colorf color,
24294  enum nk_color_format fmt)
24295 {
24296  nk_color_pick(ctx, &color, fmt);
24297  return color;
24298 }
24299 
24300 
24301 
24302 
24303 
24304 /* ==============================================================
24305  *
24306  * COMBO
24307  *
24308  * ===============================================================*/
24309 NK_INTERN int
24310 nk_combo_begin(struct nk_context *ctx, struct nk_window *win,
24311  struct nk_vec2 size, int is_clicked, struct nk_rect header)
24312 {
24313  struct nk_window *popup;
24314  int is_open = 0;
24315  int is_active = 0;
24316  struct nk_rect body;
24317  nk_hash hash;
24318 
24319  NK_ASSERT(ctx);
24320  NK_ASSERT(ctx->current);
24321  NK_ASSERT(ctx->current->layout);
24322  if (!ctx || !ctx->current || !ctx->current->layout)
24323  return 0;
24324 
24325  popup = win->popup.win;
24326  body.x = header.x;
24327  body.w = size.x;
24328  body.y = header.y + header.h-ctx->style.window.combo_border;
24329  body.h = size.y;
24330 
24331  hash = win->popup.combo_count++;
24332  is_open = (popup) ? nk_true:nk_false;
24333  is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_COMBO);
24334  if ((is_clicked && is_open && !is_active) || (is_open && !is_active) ||
24335  (!is_open && !is_active && !is_clicked)) return 0;
24336  if (!nk_nonblock_begin(ctx, 0, body,
24337  (is_clicked && is_open)?nk_rect(0,0,0,0):header, NK_PANEL_COMBO)) return 0;
24338 
24339  win->popup.type = NK_PANEL_COMBO;
24340  win->popup.name = hash;
24341  return 1;
24342 }
24343 NK_API int
24344 nk_combo_begin_text(struct nk_context *ctx, const char *selected, int len,
24345  struct nk_vec2 size)
24346 {
24347  const struct nk_input *in;
24348  struct nk_window *win;
24349  struct nk_style *style;
24350 
24351  enum nk_widget_layout_states s;
24352  int is_clicked = nk_false;
24353  struct nk_rect header;
24354  const struct nk_style_item *background;
24355  struct nk_text text;
24356 
24357  NK_ASSERT(ctx);
24358  NK_ASSERT(selected);
24359  NK_ASSERT(ctx->current);
24360  NK_ASSERT(ctx->current->layout);
24361  if (!ctx || !ctx->current || !ctx->current->layout || !selected)
24362  return 0;
24363 
24364  win = ctx->current;
24365  style = &ctx->style;
24366  s = nk_widget(&header, ctx);
24367  if (s == NK_WIDGET_INVALID)
24368  return 0;
24369 
24370  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
24371  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
24372  is_clicked = nk_true;
24373 
24374  /* draw combo box header background and border */
24376  background = &style->combo.active;
24377  text.text = style->combo.label_active;
24378  } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
24379  background = &style->combo.hover;
24380  text.text = style->combo.label_hover;
24381  } else {
24382  background = &style->combo.normal;
24383  text.text = style->combo.label_normal;
24384  }
24385  if (background->type == NK_STYLE_ITEM_IMAGE) {
24386  text.background = nk_rgba(0,0,0,0);
24387  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
24388  } else {
24389  text.background = background->data.color;
24390  nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
24391  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
24392  }
24393  {
24394  /* print currently selected text item */
24395  struct nk_rect label;
24396  struct nk_rect button;
24397  struct nk_rect content;
24398 
24399  enum nk_symbol_type sym;
24401  sym = style->combo.sym_hover;
24402  else if (is_clicked)
24403  sym = style->combo.sym_active;
24404  else sym = style->combo.sym_normal;
24405 
24406  /* calculate button */
24407  button.w = header.h - 2 * style->combo.button_padding.y;
24408  button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
24409  button.y = header.y + style->combo.button_padding.y;
24410  button.h = button.w;
24411 
24412  content.x = button.x + style->combo.button.padding.x;
24413  content.y = button.y + style->combo.button.padding.y;
24414  content.w = button.w - 2 * style->combo.button.padding.x;
24415  content.h = button.h - 2 * style->combo.button.padding.y;
24416 
24417  /* draw selected label */
24418  text.padding = nk_vec2(0,0);
24419  label.x = header.x + style->combo.content_padding.x;
24420  label.y = header.y + style->combo.content_padding.y;
24421  label.w = button.x - (style->combo.content_padding.x + style->combo.spacing.x) - label.x;;
24422  label.h = header.h - 2 * style->combo.content_padding.y;
24423  nk_widget_text(&win->buffer, label, selected, len, &text,
24424  NK_TEXT_LEFT, ctx->style.font);
24425 
24426  /* draw open/close button */
24427  nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
24428  &ctx->style.combo.button, sym, style->font);
24429  }
24430  return nk_combo_begin(ctx, win, size, is_clicked, header);
24431 }
24432 NK_API int
24433 nk_combo_begin_label(struct nk_context *ctx, const char *selected, struct nk_vec2 size)
24434 {
24435  return nk_combo_begin_text(ctx, selected, nk_strlen(selected), size);
24436 }
24437 NK_API int
24438 nk_combo_begin_color(struct nk_context *ctx, struct nk_color color, struct nk_vec2 size)
24439 {
24440  struct nk_window *win;
24441  struct nk_style *style;
24442  const struct nk_input *in;
24443 
24444  struct nk_rect header;
24445  int is_clicked = nk_false;
24446  enum nk_widget_layout_states s;
24447  const struct nk_style_item *background;
24448 
24449  NK_ASSERT(ctx);
24450  NK_ASSERT(ctx->current);
24451  NK_ASSERT(ctx->current->layout);
24452  if (!ctx || !ctx->current || !ctx->current->layout)
24453  return 0;
24454 
24455  win = ctx->current;
24456  style = &ctx->style;
24457  s = nk_widget(&header, ctx);
24458  if (s == NK_WIDGET_INVALID)
24459  return 0;
24460 
24461  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
24462  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
24463  is_clicked = nk_true;
24464 
24465  /* draw combo box header background and border */
24467  background = &style->combo.active;
24468  else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
24469  background = &style->combo.hover;
24470  else background = &style->combo.normal;
24471 
24472  if (background->type == NK_STYLE_ITEM_IMAGE) {
24473  nk_draw_image(&win->buffer, header, &background->data.image,nk_white);
24474  } else {
24475  nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
24476  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
24477  }
24478  {
24479  struct nk_rect content;
24480  struct nk_rect button;
24481  struct nk_rect bounds;
24482 
24483  enum nk_symbol_type sym;
24485  sym = style->combo.sym_hover;
24486  else if (is_clicked)
24487  sym = style->combo.sym_active;
24488  else sym = style->combo.sym_normal;
24489 
24490  /* calculate button */
24491  button.w = header.h - 2 * style->combo.button_padding.y;
24492  button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
24493  button.y = header.y + style->combo.button_padding.y;
24494  button.h = button.w;
24495 
24496  content.x = button.x + style->combo.button.padding.x;
24497  content.y = button.y + style->combo.button.padding.y;
24498  content.w = button.w - 2 * style->combo.button.padding.x;
24499  content.h = button.h - 2 * style->combo.button.padding.y;
24500 
24501  /* draw color */
24502  bounds.h = header.h - 4 * style->combo.content_padding.y;
24503  bounds.y = header.y + 2 * style->combo.content_padding.y;
24504  bounds.x = header.x + 2 * style->combo.content_padding.x;
24505  bounds.w = (button.x - (style->combo.content_padding.x + style->combo.spacing.x)) - bounds.x;
24506  nk_fill_rect(&win->buffer, bounds, 0, color);
24507 
24508  /* draw open/close button */
24509  nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
24510  &ctx->style.combo.button, sym, style->font);
24511  }
24512  return nk_combo_begin(ctx, win, size, is_clicked, header);
24513 }
24514 NK_API int
24515 nk_combo_begin_symbol(struct nk_context *ctx, enum nk_symbol_type symbol, struct nk_vec2 size)
24516 {
24517  struct nk_window *win;
24518  struct nk_style *style;
24519  const struct nk_input *in;
24520 
24521  struct nk_rect header;
24522  int is_clicked = nk_false;
24523  enum nk_widget_layout_states s;
24524  const struct nk_style_item *background;
24525  struct nk_color sym_background;
24526  struct nk_color symbol_color;
24527 
24528  NK_ASSERT(ctx);
24529  NK_ASSERT(ctx->current);
24530  NK_ASSERT(ctx->current->layout);
24531  if (!ctx || !ctx->current || !ctx->current->layout)
24532  return 0;
24533 
24534  win = ctx->current;
24535  style = &ctx->style;
24536  s = nk_widget(&header, ctx);
24537  if (s == NK_WIDGET_INVALID)
24538  return 0;
24539 
24540  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
24541  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
24542  is_clicked = nk_true;
24543 
24544  /* draw combo box header background and border */
24546  background = &style->combo.active;
24547  symbol_color = style->combo.symbol_active;
24548  } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
24549  background = &style->combo.hover;
24550  symbol_color = style->combo.symbol_hover;
24551  } else {
24552  background = &style->combo.normal;
24553  symbol_color = style->combo.symbol_hover;
24554  }
24555 
24556  if (background->type == NK_STYLE_ITEM_IMAGE) {
24557  sym_background = nk_rgba(0,0,0,0);
24558  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
24559  } else {
24560  sym_background = background->data.color;
24561  nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
24562  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
24563  }
24564  {
24565  struct nk_rect bounds = {0,0,0,0};
24566  struct nk_rect content;
24567  struct nk_rect button;
24568 
24569  enum nk_symbol_type sym;
24571  sym = style->combo.sym_hover;
24572  else if (is_clicked)
24573  sym = style->combo.sym_active;
24574  else sym = style->combo.sym_normal;
24575 
24576  /* calculate button */
24577  button.w = header.h - 2 * style->combo.button_padding.y;
24578  button.x = (header.x + header.w - header.h) - style->combo.button_padding.y;
24579  button.y = header.y + style->combo.button_padding.y;
24580  button.h = button.w;
24581 
24582  content.x = button.x + style->combo.button.padding.x;
24583  content.y = button.y + style->combo.button.padding.y;
24584  content.w = button.w - 2 * style->combo.button.padding.x;
24585  content.h = button.h - 2 * style->combo.button.padding.y;
24586 
24587  /* draw symbol */
24588  bounds.h = header.h - 2 * style->combo.content_padding.y;
24589  bounds.y = header.y + style->combo.content_padding.y;
24590  bounds.x = header.x + style->combo.content_padding.x;
24591  bounds.w = (button.x - style->combo.content_padding.y) - bounds.x;
24592  nk_draw_symbol(&win->buffer, symbol, bounds, sym_background, symbol_color,
24593  1.0f, style->font);
24594 
24595  /* draw open/close button */
24596  nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state,
24597  &ctx->style.combo.button, sym, style->font);
24598  }
24599  return nk_combo_begin(ctx, win, size, is_clicked, header);
24600 }
24601 NK_API int
24602 nk_combo_begin_symbol_text(struct nk_context *ctx, const char *selected, int len,
24603  enum nk_symbol_type symbol, struct nk_vec2 size)
24604 {
24605  struct nk_window *win;
24606  struct nk_style *style;
24607  struct nk_input *in;
24608 
24609  struct nk_rect header;
24610  int is_clicked = nk_false;
24611  enum nk_widget_layout_states s;
24612  const struct nk_style_item *background;
24613  struct nk_color symbol_color;
24614  struct nk_text text;
24615 
24616  NK_ASSERT(ctx);
24617  NK_ASSERT(ctx->current);
24618  NK_ASSERT(ctx->current->layout);
24619  if (!ctx || !ctx->current || !ctx->current->layout)
24620  return 0;
24621 
24622  win = ctx->current;
24623  style = &ctx->style;
24624  s = nk_widget(&header, ctx);
24625  if (!s) return 0;
24626 
24627  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
24628  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
24629  is_clicked = nk_true;
24630 
24631  /* draw combo box header background and border */
24633  background = &style->combo.active;
24634  symbol_color = style->combo.symbol_active;
24635  text.text = style->combo.label_active;
24636  } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
24637  background = &style->combo.hover;
24638  symbol_color = style->combo.symbol_hover;
24639  text.text = style->combo.label_hover;
24640  } else {
24641  background = &style->combo.normal;
24642  symbol_color = style->combo.symbol_normal;
24643  text.text = style->combo.label_normal;
24644  }
24645  if (background->type == NK_STYLE_ITEM_IMAGE) {
24646  text.background = nk_rgba(0,0,0,0);
24647  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
24648  } else {
24649  text.background = background->data.color;
24650  nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
24651  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
24652  }
24653  {
24654  struct nk_rect content;
24655  struct nk_rect button;
24656  struct nk_rect label;
24657  struct nk_rect image;
24658 
24659  enum nk_symbol_type sym;
24661  sym = style->combo.sym_hover;
24662  else if (is_clicked)
24663  sym = style->combo.sym_active;
24664  else sym = style->combo.sym_normal;
24665 
24666  /* calculate button */
24667  button.w = header.h - 2 * style->combo.button_padding.y;
24668  button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
24669  button.y = header.y + style->combo.button_padding.y;
24670  button.h = button.w;
24671 
24672  content.x = button.x + style->combo.button.padding.x;
24673  content.y = button.y + style->combo.button.padding.y;
24674  content.w = button.w - 2 * style->combo.button.padding.x;
24675  content.h = button.h - 2 * style->combo.button.padding.y;
24676  nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
24677  &ctx->style.combo.button, sym, style->font);
24678 
24679  /* draw symbol */
24680  image.x = header.x + style->combo.content_padding.x;
24681  image.y = header.y + style->combo.content_padding.y;
24682  image.h = header.h - 2 * style->combo.content_padding.y;
24683  image.w = image.h;
24684  nk_draw_symbol(&win->buffer, symbol, image, text.background, symbol_color,
24685  1.0f, style->font);
24686 
24687  /* draw label */
24688  text.padding = nk_vec2(0,0);
24689  label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x;
24690  label.y = header.y + style->combo.content_padding.y;
24691  label.w = (button.x - style->combo.content_padding.x) - label.x;
24692  label.h = header.h - 2 * style->combo.content_padding.y;
24693  nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font);
24694  }
24695  return nk_combo_begin(ctx, win, size, is_clicked, header);
24696 }
24697 NK_API int
24698 nk_combo_begin_image(struct nk_context *ctx, struct nk_image img, struct nk_vec2 size)
24699 {
24700  struct nk_window *win;
24701  struct nk_style *style;
24702  const struct nk_input *in;
24703 
24704  struct nk_rect header;
24705  int is_clicked = nk_false;
24706  enum nk_widget_layout_states s;
24707  const struct nk_style_item *background;
24708 
24709  NK_ASSERT(ctx);
24710  NK_ASSERT(ctx->current);
24711  NK_ASSERT(ctx->current->layout);
24712  if (!ctx || !ctx->current || !ctx->current->layout)
24713  return 0;
24714 
24715  win = ctx->current;
24716  style = &ctx->style;
24717  s = nk_widget(&header, ctx);
24718  if (s == NK_WIDGET_INVALID)
24719  return 0;
24720 
24721  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
24722  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
24723  is_clicked = nk_true;
24724 
24725  /* draw combo box header background and border */
24727  background = &style->combo.active;
24728  else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
24729  background = &style->combo.hover;
24730  else background = &style->combo.normal;
24731 
24732  if (background->type == NK_STYLE_ITEM_IMAGE) {
24733  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
24734  } else {
24735  nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
24736  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
24737  }
24738  {
24739  struct nk_rect bounds = {0,0,0,0};
24740  struct nk_rect content;
24741  struct nk_rect button;
24742 
24743  enum nk_symbol_type sym;
24745  sym = style->combo.sym_hover;
24746  else if (is_clicked)
24747  sym = style->combo.sym_active;
24748  else sym = style->combo.sym_normal;
24749 
24750  /* calculate button */
24751  button.w = header.h - 2 * style->combo.button_padding.y;
24752  button.x = (header.x + header.w - header.h) - style->combo.button_padding.y;
24753  button.y = header.y + style->combo.button_padding.y;
24754  button.h = button.w;
24755 
24756  content.x = button.x + style->combo.button.padding.x;
24757  content.y = button.y + style->combo.button.padding.y;
24758  content.w = button.w - 2 * style->combo.button.padding.x;
24759  content.h = button.h - 2 * style->combo.button.padding.y;
24760 
24761  /* draw image */
24762  bounds.h = header.h - 2 * style->combo.content_padding.y;
24763  bounds.y = header.y + style->combo.content_padding.y;
24764  bounds.x = header.x + style->combo.content_padding.x;
24765  bounds.w = (button.x - style->combo.content_padding.y) - bounds.x;
24766  nk_draw_image(&win->buffer, bounds, &img, nk_white);
24767 
24768  /* draw open/close button */
24769  nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state,
24770  &ctx->style.combo.button, sym, style->font);
24771  }
24772  return nk_combo_begin(ctx, win, size, is_clicked, header);
24773 }
24774 NK_API int
24775 nk_combo_begin_image_text(struct nk_context *ctx, const char *selected, int len,
24776  struct nk_image img, struct nk_vec2 size)
24777 {
24778  struct nk_window *win;
24779  struct nk_style *style;
24780  struct nk_input *in;
24781 
24782  struct nk_rect header;
24783  int is_clicked = nk_false;
24784  enum nk_widget_layout_states s;
24785  const struct nk_style_item *background;
24786  struct nk_text text;
24787 
24788  NK_ASSERT(ctx);
24789  NK_ASSERT(ctx->current);
24790  NK_ASSERT(ctx->current->layout);
24791  if (!ctx || !ctx->current || !ctx->current->layout)
24792  return 0;
24793 
24794  win = ctx->current;
24795  style = &ctx->style;
24796  s = nk_widget(&header, ctx);
24797  if (!s) return 0;
24798 
24799  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
24800  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
24801  is_clicked = nk_true;
24802 
24803  /* draw combo box header background and border */
24805  background = &style->combo.active;
24806  text.text = style->combo.label_active;
24807  } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
24808  background = &style->combo.hover;
24809  text.text = style->combo.label_hover;
24810  } else {
24811  background = &style->combo.normal;
24812  text.text = style->combo.label_normal;
24813  }
24814  if (background->type == NK_STYLE_ITEM_IMAGE) {
24815  text.background = nk_rgba(0,0,0,0);
24816  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
24817  } else {
24818  text.background = background->data.color;
24819  nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
24820  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
24821  }
24822  {
24823  struct nk_rect content;
24824  struct nk_rect button;
24825  struct nk_rect label;
24826  struct nk_rect image;
24827 
24828  enum nk_symbol_type sym;
24830  sym = style->combo.sym_hover;
24831  else if (is_clicked)
24832  sym = style->combo.sym_active;
24833  else sym = style->combo.sym_normal;
24834 
24835  /* calculate button */
24836  button.w = header.h - 2 * style->combo.button_padding.y;
24837  button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
24838  button.y = header.y + style->combo.button_padding.y;
24839  button.h = button.w;
24840 
24841  content.x = button.x + style->combo.button.padding.x;
24842  content.y = button.y + style->combo.button.padding.y;
24843  content.w = button.w - 2 * style->combo.button.padding.x;
24844  content.h = button.h - 2 * style->combo.button.padding.y;
24845  nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
24846  &ctx->style.combo.button, sym, style->font);
24847 
24848  /* draw image */
24849  image.x = header.x + style->combo.content_padding.x;
24850  image.y = header.y + style->combo.content_padding.y;
24851  image.h = header.h - 2 * style->combo.content_padding.y;
24852  image.w = image.h;
24853  nk_draw_image(&win->buffer, image, &img, nk_white);
24854 
24855  /* draw label */
24856  text.padding = nk_vec2(0,0);
24857  label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x;
24858  label.y = header.y + style->combo.content_padding.y;
24859  label.w = (button.x - style->combo.content_padding.x) - label.x;
24860  label.h = header.h - 2 * style->combo.content_padding.y;
24861  nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font);
24862  }
24863  return nk_combo_begin(ctx, win, size, is_clicked, header);
24864 }
24865 NK_API int
24867  const char *selected, enum nk_symbol_type type, struct nk_vec2 size)
24868 {
24869  return nk_combo_begin_symbol_text(ctx, selected, nk_strlen(selected), type, size);
24870 }
24871 NK_API int
24873  const char *selected, struct nk_image img, struct nk_vec2 size)
24874 {
24875  return nk_combo_begin_image_text(ctx, selected, nk_strlen(selected), img, size);
24876 }
24877 NK_API int
24878 nk_combo_item_text(struct nk_context *ctx, const char *text, int len,nk_flags align)
24879 {
24880  return nk_contextual_item_text(ctx, text, len, align);
24881 }
24882 NK_API int
24883 nk_combo_item_label(struct nk_context *ctx, const char *label, nk_flags align)
24884 {
24885  return nk_contextual_item_label(ctx, label, align);
24886 }
24887 NK_API int
24888 nk_combo_item_image_text(struct nk_context *ctx, struct nk_image img, const char *text,
24889  int len, nk_flags alignment)
24890 {
24891  return nk_contextual_item_image_text(ctx, img, text, len, alignment);
24892 }
24893 NK_API int
24894 nk_combo_item_image_label(struct nk_context *ctx, struct nk_image img,
24895  const char *text, nk_flags alignment)
24896 {
24897  return nk_contextual_item_image_label(ctx, img, text, alignment);
24898 }
24899 NK_API int
24901  const char *text, int len, nk_flags alignment)
24902 {
24903  return nk_contextual_item_symbol_text(ctx, sym, text, len, alignment);
24904 }
24905 NK_API int
24907  const char *label, nk_flags alignment)
24908 {
24909  return nk_contextual_item_symbol_label(ctx, sym, label, alignment);
24910 }
24911 NK_API void nk_combo_end(struct nk_context *ctx)
24912 {
24913  nk_contextual_end(ctx);
24914 }
24915 NK_API void nk_combo_close(struct nk_context *ctx)
24916 {
24917  nk_contextual_close(ctx);
24918 }
24919 NK_API int
24920 nk_combo(struct nk_context *ctx, const char **items, int count,
24921  int selected, int item_height, struct nk_vec2 size)
24922 {
24923  int i = 0;
24924  int max_height;
24925  struct nk_vec2 item_spacing;
24926  struct nk_vec2 window_padding;
24927 
24928  NK_ASSERT(ctx);
24929  NK_ASSERT(items);
24930  NK_ASSERT(ctx->current);
24931  if (!ctx || !items ||!count)
24932  return selected;
24933 
24934  item_spacing = ctx->style.window.spacing;
24935  window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
24936  max_height = count * item_height + count * (int)item_spacing.y;
24937  max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
24938  size.y = NK_MIN(size.y, (float)max_height);
24939  if (nk_combo_begin_label(ctx, items[selected], size)) {
24940  nk_layout_row_dynamic(ctx, (float)item_height, 1);
24941  for (i = 0; i < count; ++i) {
24942  if (nk_combo_item_label(ctx, items[i], NK_TEXT_LEFT))
24943  selected = i;
24944  }
24945  nk_combo_end(ctx);
24946  }
24947  return selected;
24948 }
24949 NK_API int
24950 nk_combo_separator(struct nk_context *ctx, const char *items_separated_by_separator,
24951  int separator, int selected, int count, int item_height, struct nk_vec2 size)
24952 {
24953  int i;
24954  int max_height;
24955  struct nk_vec2 item_spacing;
24956  struct nk_vec2 window_padding;
24957  const char *current_item;
24958  const char *iter;
24959  int length = 0;
24960 
24961  NK_ASSERT(ctx);
24962  NK_ASSERT(items_separated_by_separator);
24963  if (!ctx || !items_separated_by_separator)
24964  return selected;
24965 
24966  /* calculate popup window */
24967  item_spacing = ctx->style.window.spacing;
24968  window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
24969  max_height = count * item_height + count * (int)item_spacing.y;
24970  max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
24971  size.y = NK_MIN(size.y, (float)max_height);
24972 
24973  /* find selected item */
24974  current_item = items_separated_by_separator;
24975  for (i = 0; i < count; ++i) {
24976  iter = current_item;
24977  while (*iter && *iter != separator) iter++;
24978  length = (int)(iter - current_item);
24979  if (i == selected) break;
24980  current_item = iter + 1;
24981  }
24982 
24983  if (nk_combo_begin_text(ctx, current_item, length, size)) {
24984  current_item = items_separated_by_separator;
24985  nk_layout_row_dynamic(ctx, (float)item_height, 1);
24986  for (i = 0; i < count; ++i) {
24987  iter = current_item;
24988  while (*iter && *iter != separator) iter++;
24989  length = (int)(iter - current_item);
24990  if (nk_combo_item_text(ctx, current_item, length, NK_TEXT_LEFT))
24991  selected = i;
24992  current_item = current_item + length + 1;
24993  }
24994  nk_combo_end(ctx);
24995  }
24996  return selected;
24997 }
24998 NK_API int
24999 nk_combo_string(struct nk_context *ctx, const char *items_separated_by_zeros,
25000  int selected, int count, int item_height, struct nk_vec2 size)
25001 {
25002  return nk_combo_separator(ctx, items_separated_by_zeros, '\0', selected, count, item_height, size);
25003 }
25004 NK_API int
25005 nk_combo_callback(struct nk_context *ctx, void(*item_getter)(void*, int, const char**),
25006  void *userdata, int selected, int count, int item_height, struct nk_vec2 size)
25007 {
25008  int i;
25009  int max_height;
25010  struct nk_vec2 item_spacing;
25011  struct nk_vec2 window_padding;
25012  const char *item;
25013 
25014  NK_ASSERT(ctx);
25015  NK_ASSERT(item_getter);
25016  if (!ctx || !item_getter)
25017  return selected;
25018 
25019  /* calculate popup window */
25020  item_spacing = ctx->style.window.spacing;
25021  window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
25022  max_height = count * item_height + count * (int)item_spacing.y;
25023  max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
25024  size.y = NK_MIN(size.y, (float)max_height);
25025 
25026  item_getter(userdata, selected, &item);
25027  if (nk_combo_begin_label(ctx, item, size)) {
25028  nk_layout_row_dynamic(ctx, (float)item_height, 1);
25029  for (i = 0; i < count; ++i) {
25030  item_getter(userdata, i, &item);
25031  if (nk_combo_item_label(ctx, item, NK_TEXT_LEFT))
25032  selected = i;
25033  }
25034  nk_combo_end(ctx);
25035  } return selected;
25036 }
25037 NK_API void
25038 nk_combobox(struct nk_context *ctx, const char **items, int count,
25039  int *selected, int item_height, struct nk_vec2 size)
25040 {
25041  *selected = nk_combo(ctx, items, count, *selected, item_height, size);
25042 }
25043 NK_API void
25044 nk_combobox_string(struct nk_context *ctx, const char *items_separated_by_zeros,
25045  int *selected, int count, int item_height, struct nk_vec2 size)
25046 {
25047  *selected = nk_combo_string(ctx, items_separated_by_zeros, *selected, count, item_height, size);
25048 }
25049 NK_API void
25050 nk_combobox_separator(struct nk_context *ctx, const char *items_separated_by_separator,
25051  int separator,int *selected, int count, int item_height, struct nk_vec2 size)
25052 {
25053  *selected = nk_combo_separator(ctx, items_separated_by_separator, separator,
25054  *selected, count, item_height, size);
25055 }
25056 NK_API void
25057 nk_combobox_callback(struct nk_context *ctx,
25058  void(*item_getter)(void* data, int id, const char **out_text),
25059  void *userdata, int *selected, int count, int item_height, struct nk_vec2 size)
25060 {
25061  *selected = nk_combo_callback(ctx, item_getter, userdata, *selected, count, item_height, size);
25062 }
25063 
25064 
25065 
25066 
25067 
25068 /* ===============================================================
25069  *
25070  * TOOLTIP
25071  *
25072  * ===============================================================*/
25073 NK_API int
25074 nk_tooltip_begin(struct nk_context *ctx, float width)
25075 {
25076  int x,y,w,h;
25077  struct nk_window *win;
25078  const struct nk_input *in;
25079  struct nk_rect bounds;
25080  int ret;
25081 
25082  NK_ASSERT(ctx);
25083  NK_ASSERT(ctx->current);
25084  NK_ASSERT(ctx->current->layout);
25085  if (!ctx || !ctx->current || !ctx->current->layout)
25086  return 0;
25087 
25088  /* make sure that no nonblocking popup is currently active */
25089  win = ctx->current;
25090  in = &ctx->input;
25091  if (win->popup.win && (win->popup.type & NK_PANEL_SET_NONBLOCK))
25092  return 0;
25093 
25094  w = nk_iceilf(width);
25095  h = nk_iceilf(nk_null_rect.h);
25096  x = nk_ifloorf(in->mouse.pos.x + 1) - (int)win->layout->clip.x;
25097  y = nk_ifloorf(in->mouse.pos.y + 1) - (int)win->layout->clip.y;
25098 
25099  bounds.x = (float)x;
25100  bounds.y = (float)y;
25101  bounds.w = (float)w;
25102  bounds.h = (float)h;
25103 
25104  ret = nk_popup_begin(ctx, NK_POPUP_DYNAMIC,
25105  "__##Tooltip##__", NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER, bounds);
25106  if (ret) win->layout->flags &= ~(nk_flags)NK_WINDOW_ROM;
25107  win->popup.type = NK_PANEL_TOOLTIP;
25109  return ret;
25110 }
25111 
25112 NK_API void
25113 nk_tooltip_end(struct nk_context *ctx)
25114 {
25115  NK_ASSERT(ctx);
25116  NK_ASSERT(ctx->current);
25117  if (!ctx || !ctx->current) return;
25118  ctx->current->seq--;
25119  nk_popup_close(ctx);
25120  nk_popup_end(ctx);
25121 }
25122 NK_API void
25123 nk_tooltip(struct nk_context *ctx, const char *text)
25124 {
25125  const struct nk_style *style;
25126  struct nk_vec2 padding;
25127 
25128  int text_len;
25129  float text_width;
25130  float text_height;
25131 
25132  NK_ASSERT(ctx);
25133  NK_ASSERT(ctx->current);
25134  NK_ASSERT(ctx->current->layout);
25135  NK_ASSERT(text);
25136  if (!ctx || !ctx->current || !ctx->current->layout || !text)
25137  return;
25138 
25139  /* fetch configuration data */
25140  style = &ctx->style;
25141  padding = style->window.padding;
25142 
25143  /* calculate size of the text and tooltip */
25144  text_len = nk_strlen(text);
25145  text_width = style->font->width(style->font->userdata,
25146  style->font->height, text, text_len);
25147  text_width += (4 * padding.x);
25148  text_height = (style->font->height + 2 * padding.y);
25149 
25150  /* execute tooltip and fill with text */
25151  if (nk_tooltip_begin(ctx, (float)text_width)) {
25152  nk_layout_row_dynamic(ctx, (float)text_height, 1);
25153  nk_text(ctx, text, text_len, NK_TEXT_LEFT);
25154  nk_tooltip_end(ctx);
25155  }
25156 }
25157 #ifdef NK_INCLUDE_STANDARD_VARARGS
25158 NK_API void
25159 nk_tooltipf(struct nk_context *ctx, const char *fmt, ...)
25160 {
25161  va_list args;
25162  va_start(args, fmt);
25163  nk_tooltipfv(ctx, fmt, args);
25164  va_end(args);
25165 }
25166 NK_API void
25167 nk_tooltipfv(struct nk_context *ctx, const char *fmt, va_list args)
25168 {
25169  char buf[256];
25170  nk_strfmt(buf, NK_LEN(buf), fmt, args);
25171  nk_tooltip(ctx, buf);
25172 }
25173 #endif
25174 
25175 
25176 
25177 #endif /* NK_IMPLEMENTATION */
25178 
25179 /*
25222 
25500 
25525 */
25526 
unsigned short r
Definition: nuklear.h:4423
struct nk_vec2 padding
Definition: nuklear.h:4988
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:4996
NK_API struct nk_color nk_rgb_iv(const int *rgb)
struct nk_command header
Definition: nuklear.h:4336
NK_API int nk_menu_item_text(struct nk_context *, const char *, int, nk_flags align)
struct nk_style_item hover
Definition: nuklear.h:4938
nk_chart_event
Definition: nuklear.h:473
struct nk_vec2 padding
Definition: nuklear.h:4894
float preferred_x
Definition: nuklear.h:4220
struct nk_style_item hover_active
Definition: nuklear.h:4810
NK_API int nk_window_has_focus(const struct nk_context *)
NK_API int nk_menu_item_symbol_text(struct nk_context *, enum nk_symbol_type, const char *, int, nk_flags alignment)
struct nk_style_button dec_button
Definition: nuklear.h:4992
NK_API struct nk_rect nk_rectv(const float *xywh)
nk_handle userdata
Definition: nuklear.h:4897
#define NK_CONFIG_STACK(type, size)
Definition: nuklear.h:5413
struct nk_style_item cursor_hover
Definition: nuklear.h:4781
struct nk_command header
Definition: nuklear.h:4389
NK_API int nk_input_mouse_clicked(const struct nk_input *, enum nk_buttons, struct nk_rect)
struct nk_pool pool
Definition: nuklear.h:5520
struct nk_style_item active
Definition: nuklear.h:4841
NK_API int nk_select_text(struct nk_context *, const char *, int, nk_flags align, int value)
NK_API int nk_tree_state_image_push(struct nk_context *, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states *state)
unsigned int scrolled
Definition: nuklear.h:5344
NK_API struct nk_color nk_rgba_bv(const nk_byte *rgba)
float menu_border
Definition: nuklear.h:5112
NK_API int nk_contextual_item_image_text(struct nk_context *, struct nk_image, const char *, int len, nk_flags alignment)
NK_API void nk_textedit_select_all(struct nk_text_edit *)
struct nk_style_button close_button
Definition: nuklear.h:5077
nk_convert_result
Definition: nuklear.h:1133
NK_API int nk_button_symbol_label_styled(struct nk_context *ctx, const struct nk_style_button *style, enum nk_symbol_type symbol, const char *title, nk_flags align)
NK_API int nk_contextual_begin(struct nk_context *, nk_flags, struct nk_vec2, struct nk_rect trigger_bounds)
struct nk_vec2 last
Definition: nuklear.h:5194
struct nk_color label_normal
Definition: nuklear.h:5084
struct nk_color text_hover
Definition: nuklear.h:4815
struct nk_style_item cursor_normal
Definition: nuklear.h:4780
NK_API void nk_color_hex_rgb(char *output, struct nk_color)
float rounding_cursor
Definition: nuklear.h:4919
float border
Definition: nuklear.h:5254
NK_API struct nk_rect nk_get_null_rect(void)
nk_buffer_allocation_type
Definition: nuklear.h:4030
NK_API int nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags)
struct nk_color color
Definition: nuklear.h:4425
#define NK_STORAGE
Definition: nuklear.h:271
nk_handle userdata
Definition: nuklear.h:4871
nk_widget_states
Definition: nuklear.h:2972
float tooltip_border
Definition: nuklear.h:5114
float max_x
Definition: nuklear.h:5251
#define NK_INT32
Definition: nuklear.h:353
NK_API int nk_contextual_item_symbol_text(struct nk_context *, enum nk_symbol_type, const char *, int, nk_flags alignment)
NK_API int nk_filter_default(const struct nk_text_edit *, nk_rune unicode)
unsigned int page_count
Definition: nuklear.h:5481
nk_size allocated
Definition: nuklear.h:4053
NK_API void nk_stroke_circle(struct nk_command_buffer *, struct nk_rect, float line_thickness, struct nk_color)
NK_API struct nk_vec2 nk_vec2i(int x, int y)
struct nk_vec2 contextual_padding
Definition: nuklear.h:5127
nk_panel_flags
Definition: nuklear.h:1438
NK_API int nk_utf_decode(const char *, nk_rune *, int)
struct nk_style_button menu_button
Definition: nuklear.h:5142
NK_API struct nk_color nk_rgba_u32(nk_uint)
nk_size needed
Definition: nuklear.h:4055
float(* nk_text_width_f)(nk_handle, float h, const char *, int len)
Definition: nuklear.h:3820
NK_API int nk_filter_hex(const struct nk_text_edit *, nk_rune unicode)
NK_API int nk_menu_item_image_text(struct nk_context *, struct nk_image, const char *, int len, nk_flags alignment)
float bar_height
Definition: nuklear.h:4858
unsigned short w
Definition: nuklear.h:4365
NK_API void nk_buffer_init(struct nk_buffer *, const struct nk_allocator *, nk_size size)
NK_API int nk_button_color(struct nk_context *, struct nk_color)
unsigned short h
Definition: nuklear.h:4407
NK_API int nk_select_image_text(struct nk_context *, struct nk_image, const char *, int, nk_flags align, int value)
NK_API struct nk_window * nk_window_find(struct nk_context *ctx, const char *name)
NK_API void nk_str_remove_chars(struct nk_str *, int len)
NK_API int nk_widget_is_hovered(struct nk_context *)
#define NK_FLAGS_STACK_SIZE
Definition: nuklear.h:5401
NK_API void nk_layout_row_end(struct nk_context *)
NK_API void nk_fill_circle(struct nk_command_buffer *, struct nk_rect, struct nk_color)
struct nk_vec2 padding
Definition: nuklear.h:4742
#define nk_zero_struct(s)
Definition: nuklear.h:5556
struct nk_color label_active
Definition: nuklear.h:5086
struct nk_image img
Definition: nuklear.h:463
struct nk_color text_normal
Definition: nuklear.h:4754
nk_handle handle
Definition: nuklear.h:462
unsigned int seq
Definition: nuklear.h:5304
enum nk_symbol_type sym_left
Definition: nuklear.h:4982
struct nk_config_stack_button_behavior button_behaviors
Definition: nuklear.h:5443
nk_flags text_alignment
Definition: nuklear.h:4757
struct nk_rect clip
Definition: nuklear.h:5256
nk_modify
Definition: nuklear.h:468
struct nk_color selected_text_hover
Definition: nuklear.h:4958
NK_API int nk_combo_callback(struct nk_context *, void(*item_getter)(void *, int, const char **), void *userdata, int selected, int count, int item_height, struct nk_vec2 size)
NK_API int nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, struct nk_rect b, int down)
NK_API void nk_colorf_hsva_fv(float *hsva, struct nk_colorf in)
short h
Definition: nuklear.h:459
NK_API void nk_str_init_fixed(struct nk_str *, void *memory, nk_size size)
struct nk_color col
Definition: nuklear.h:4456
NK_API int nk_popup_begin(struct nk_context *, enum nk_popup_type, const char *, nk_flags, struct nk_rect bounds)
NK_API void nk_property_float(struct nk_context *, const char *name, float min, float *val, float max, float step, float inc_per_pixel)
NK_API void nk_layout_row_template_push_variable(struct nk_context *, float min_width)
nk_style_header_align
Definition: nuklear.h:5066
struct nk_vec2 touch_padding
Definition: nuklear.h:4792
NK_API int nk_button_text_styled(struct nk_context *, const struct nk_style_button *, const char *title, int len)
struct nk_row_layout row
Definition: nuklear.h:5258
unsigned short line_thickness
Definition: nuklear.h:4446
unsigned int seq
Definition: nuklear.h:5453
struct nk_style_button node_maximize_button
Definition: nuklear.h:5053
NK_API void nk_layout_row_template_push_static(struct nk_context *, float width)
NK_API void nk_color_hsv_iv(int *hsv_out, struct nk_color)
struct nk_vec2 tooltip_padding
Definition: nuklear.h:5129
NK_API void nk_combobox_callback(struct nk_context *, void(*item_getter)(void *, int, const char **), void *, int *selected, int count, int item_height, struct nk_vec2 size)
NK_API int nk_combo_item_text(struct nk_context *, const char *, int, nk_flags alignment)
NK_API nk_flags nk_edit_string_zero_terminated(struct nk_context *, nk_flags, char *buffer, int max, nk_plugin_filter)
struct nk_window * current
Definition: nuklear.h:5524
NK_API void nk_text(struct nk_context *, const char *, int, nk_flags)
nk_flags flags
Definition: nuklear.h:5332
struct nk_color color
Definition: nuklear.h:4393
nk_uint values[NK_VALUE_PAGE_CAPACITY]
Definition: nuklear.h:5456
float border
Definition: nuklear.h:5008
NK_API int nk_select_label(struct nk_context *, const char *, nk_flags align, int value)
float h
Definition: nuklear.h:5200
NK_API int nk_menu_item_label(struct nk_context *, const char *, nk_flags alignment)
struct nk_color color
Definition: nuklear.h:4340
float cursor_size
Definition: nuklear.h:4963
NK_API struct nk_rect nk_layout_widget_bounds(struct nk_context *)
struct nk_vec2i c
Definition: nuklear.h:4384
struct nk_color selected_text_normal
Definition: nuklear.h:4957
float w
Definition: nuklear.h:5200
NK_API int nk_button_symbol_styled(struct nk_context *, const struct nk_style_button *, enum nk_symbol_type)
float item_height
Definition: nuklear.h:5224
struct nk_color color
Definition: nuklear.h:4349
struct nk_chart_slot slots[NK_CHART_MAX_SLOT]
Definition: nuklear.h:5201
struct nk_color text_normal_active
Definition: nuklear.h:4819
char nk_glyph[NK_UTF_SIZE]
Definition: nuklear.h:460
nk_plugin_free free
Definition: nuklear.h:488
NK_POINTER_TYPE nk_ptr
Definition: nuklear.h:403
NK_API struct nk_rect nk_layout_space_rect_to_local(struct nk_context *, struct nk_rect)
nk_handle texture
Definition: nuklear.h:1141
NK_API struct nk_color nk_hsv(int h, int s, int v)
struct nk_chart chart
Definition: nuklear.h:5259
struct nk_color tooltip_border_color
Definition: nuklear.h:5106
struct nk_vec2 image_padding
Definition: nuklear.h:4829
nk_flags text_alignment
Definition: nuklear.h:4823
struct nk_vec2 cursor_size
Definition: nuklear.h:4861
struct nk_color group_border_color
Definition: nuklear.h:5105
struct nk_style_item scaler
Definition: nuklear.h:5107
#define NK_ABS(a)
Definition: nuklear.h:5540
nk_buttons
Definition: nuklear.h:767
NK_API void nk_edit_focus(struct nk_context *, nk_flags flags)
unsigned short point_count
Definition: nuklear.h:4432
#define NK_MAX_FLOAT_PRECISION
Definition: nuklear.h:5535
#define NK_MAX_NUMBER_BUFFER
Definition: nuklear.h:237
unsigned char ungrab
Definition: nuklear.h:4536
nk_edit_types
Definition: nuklear.h:3356
NK_API struct nk_color nk_hsv_fv(const float *hsv)
NK_API struct nk_style_item nk_style_item_image(struct nk_image img)
nk_anti_aliasing
Definition: nuklear.h:1132
NK_API int nk_widget_is_mouse_clicked(struct nk_context *, enum nk_buttons)
struct nk_color bar_hover
Definition: nuklear.h:4846
struct nk_style_progress progress
Definition: nuklear.h:5147
NK_API void nk_window_collapse(struct nk_context *, const char *name, enum nk_collapse_states state)
short y
Definition: nuklear.h:459
NK_API void nk_button_set_behavior(struct nk_context *, enum nk_button_behavior)
nk_handle userdata
Definition: nuklear.h:4172
NK_API void nk_group_end(struct nk_context *)
NK_API int nk_input_is_key_pressed(const struct nk_input *, enum nk_keys)
unsigned short point_count
Definition: nuklear.h:4439
struct nk_style_item normal
Definition: nuklear.h:4804
#define NK_FLAG(x)
Definition: nuklear.h:274
unsigned short w
Definition: nuklear.h:4357
unsigned short line_thickness
Definition: nuklear.h:4337
#define NK_UTF_INVALID
Definition: nuklear.h:5534
unsigned short h
Definition: nuklear.h:4454
struct nk_color top
Definition: nuklear.h:4374
struct nk_property_state property
Definition: nuklear.h:5341
NK_API void nk_layout_space_end(struct nk_context *)
#define NK_GLOBAL
Definition: nuklear.h:272
struct nk_style_item active
Definition: nuklear.h:4939
struct nk_style_item cursor_hover
Definition: nuklear.h:4852
nk_flags flags
Definition: nuklear.h:5247
struct nk_color border_color
Definition: nuklear.h:5100
struct nk_color text_pressed
Definition: nuklear.h:4816
NK_API void nk_layout_row_template_push_dynamic(struct nk_context *)
unsigned short w
Definition: nuklear.h:4454
struct nk_style_item normal
Definition: nuklear.h:4747
struct nk_page_element * freelist
Definition: nuklear.h:5525
struct nk_vec2i c
Definition: nuklear.h:4392
struct nk_style_selectable selectable
Definition: nuklear.h:5145
NK_API int nk_str_insert_str_runes(struct nk_str *, int pos, const nk_rune *)
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:4872
enum nk_symbol_type sym_minimize
Definition: nuklear.h:5055
struct nk_style_button inc_button
Definition: nuklear.h:4865
nk_handle userdata
Definition: nuklear.h:4797
#define NK_ALIGNOF(t)
Definition: nuklear.h:5599
struct nk_style_window window
Definition: nuklear.h:5155
float height
Definition: nuklear.h:5219
unsigned char grab
Definition: nuklear.h:4534
enum nk_symbol_type dec_symbol
Definition: nuklear.h:4927
int select_start
Definition: nuklear.h:4211
struct nk_vec2i ctrl[2]
Definition: nuklear.h:4348
float group_border
Definition: nuklear.h:5113
NK_API void nk_stroke_triangle(struct nk_command_buffer *, float, float, float, float, float, float, float line_thichness, struct nk_color)
NK_SIZE_TYPE nk_size
Definition: nuklear.h:402
unsigned short w
Definition: nuklear.h:4332
unsigned short line_thickness
Definition: nuklear.h:4381
struct nk_color border_color
Definition: nuklear.h:4940
struct nk_color text_normal
Definition: nuklear.h:4814
nk_panel_row_layout_type
Definition: nuklear.h:5204
struct nk_style_button contextual_button
Definition: nuklear.h:5141
NK_API void nk_label_wrap(struct nk_context *, const char *)
NK_API struct nk_color nk_hsv_bv(const nk_byte *hsv)
struct nk_style_item hover
Definition: nuklear.h:4748
NK_API int nk_strmatch_fuzzy_text(const char *txt, int txt_len, const char *pattern, int *out_score)
NK_API void nk_window_set_focus(struct nk_context *, const char *name)
NK_API void nk_str_delete_runes(struct nk_str *, int pos, int len)
struct nk_vec2 padding
Definition: nuklear.h:4920
#define NK_POINTER_TYPE
Definition: nuklear.h:390
unsigned int seq
Definition: nuklear.h:5323
NK_API struct nk_color nk_hsva_bv(const nk_byte *hsva)
NK_API int nk_utf_encode(nk_rune, char *, int)
NK_API void nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color)
nk_byte r
Definition: nuklear.h:454
float a[2]
Definition: nuklear.h:4416
NK_API int nk_str_append_text_char(struct nk_str *, const char *, int)
struct nk_color border_color
Definition: nuklear.h:5018
NK_API struct nk_colorf nk_hsva_colorfv(float *c)
float rounding
Definition: nuklear.h:4761
NK_API void nk_fill_rect_multi_color(struct nk_command_buffer *, struct nk_rect, struct nk_color left, struct nk_color top, struct nk_color right, struct nk_color bottom)
struct nk_memory memory
Definition: nuklear.h:4049
NK_API void nk_list_view_end(struct nk_list_view *)
struct nk_color color
Definition: nuklear.h:4445
float header_height
Definition: nuklear.h:5253
unsigned con_old
Definition: nuklear.h:5297
NK_API struct nk_vec2 nk_layout_space_to_local(struct nk_context *, struct nk_vec2)
struct nk_image img
Definition: nuklear.h:4455
nk_size begin
Definition: nuklear.h:5233
NK_API char * nk_str_at_rune(struct nk_str *, int pos, nk_rune *unicode, int *len)
struct nk_mouse_button buttons[NK_BUTTON_MAX]
Definition: nuklear.h:4529
struct nk_vec2 clicked_pos
Definition: nuklear.h:4526
unsigned char has_preferred_x
Definition: nuklear.h:4216
NK_API struct nk_rect nk_layout_space_rect_to_screen(struct nk_context *, struct nk_rect)
struct nk_window * parent
Definition: nuklear.h:5352
union nk_style_item_data data
Definition: nuklear.h:4737
#define S
Definition: Map.hpp:22
NK_API nk_uint nk_color_u32(struct nk_color)
NK_API struct nk_vec2 nk_widget_position(struct nk_context *)
struct nk_color background
Definition: nuklear.h:5098
NK_API int nk_button_symbol_text(struct nk_context *, enum nk_symbol_type, const char *, int, nk_flags alignment)
NK_API int nk_filter_ascii(const struct nk_text_edit *, nk_rune unicode)
struct nk_color bottom
Definition: nuklear.h:4375
nk_popup_type
Definition: nuklear.h:475
NK_API int nk_contextual_item_text(struct nk_context *, const char *, int, nk_flags align)
struct nk_page_element * next
Definition: nuklear.h:5468
nk_uint nk_flags
Definition: nuklear.h:406
float at_x
Definition: nuklear.h:5251
NK_API int nk_str_insert_text_char(struct nk_str *, int pos, const char *, int)
struct nk_window * active
Definition: nuklear.h:5523
struct nk_color highlight
Definition: nuklear.h:5191
struct nk_color color
Definition: nuklear.h:5005
float rounding
Definition: nuklear.h:5060
float at_y
Definition: nuklear.h:5251
struct nk_style_text text
Definition: nuklear.h:5139
struct nk_vec2i b
Definition: nuklear.h:4391
nk_handle userdata
Definition: nuklear.h:4832
struct nk_color text_pressed_active
Definition: nuklear.h:4821
struct nk_color label_normal
Definition: nuklear.h:5021
struct nk_color combo_border_color
Definition: nuklear.h:5102
NK_API void nk_textedit_text(struct nk_text_edit *, const char *, int total_len)
NK_API void nk_str_delete_chars(struct nk_str *, int pos, int len)
struct nk_popup_buffer buf
Definition: nuklear.h:5293
struct nk_color color
Definition: nuklear.h:4732
nk_hash name
Definition: nuklear.h:5294
struct nk_allocator alloc
Definition: nuklear.h:5479
NK_API int nk_str_append_text_runes(struct nk_str *, const nk_rune *, int)
#define NK_INT8
Definition: nuklear.h:338
nk_command_custom_callback callback
Definition: nuklear.h:4466
NK_API void nk_color_f(float *r, float *g, float *b, float *a, struct nk_color)
NK_INT8 nk_char
Definition: nuklear.h:395
NK_API void nk_color_hsv_bv(nk_byte *hsv_out, struct nk_color)
struct nk_table * tables
Definition: nuklear.h:5346
struct nk_vec2 scrollbar_size
Definition: nuklear.h:5120
NK_API int nk_strtoi(const char *str, const char **endptr)
struct nk_vec2 prev
Definition: nuklear.h:4531
enum nk_symbol_type sym_normal
Definition: nuklear.h:5032
struct nk_table * next
Definition: nuklear.h:5457
struct nk_style_item cursor_hover
Definition: nuklear.h:4885
struct nk_key keys[NK_KEY_MAX]
Definition: nuklear.h:4544
NK_API struct nk_style_item nk_style_item_hide(void)
NK_API int nk_combo_item_symbol_text(struct nk_context *, enum nk_symbol_type, const char *, int, nk_flags alignment)
unsigned short line_thickness
Definition: nuklear.h:4431
NK_API void nk_label(struct nk_context *, const char *, nk_flags align)
nk_byte g
Definition: nuklear.h:454
NK_API int nk_style_set_cursor(struct nk_context *, enum nk_style_cursor)
struct nk_color text_hover
Definition: nuklear.h:4755
NK_API const struct nk_command * nk__next(struct nk_context *, const struct nk_command *)
nk_tree_type
Definition: nuklear.h:477
NK_API int nk_stricmp(const char *s1, const char *s2)
NK_API int nk_str_insert_at_rune(struct nk_str *, int pos, const char *, int)
NK_API void nk_plot(struct nk_context *, enum nk_chart_type, const float *values, int count, int offset)
unsigned curve_segment_count
Definition: nuklear.h:1150
nk_panel_type
Definition: nuklear.h:5172
float delta_time_seconds
Definition: nuklear.h:5498
NK_API void nk_contextual_end(struct nk_context *)
NK_API int nk_combo_item_symbol_label(struct nk_context *, enum nk_symbol_type, const char *, nk_flags alignment)
struct nk_command_buffer overlay
Definition: nuklear.h:5515
struct nk_command header
Definition: nuklear.h:4353
NK_API int nk_progress(struct nk_context *, nk_size *cur, nk_size max, int modifyable)
nk_size needed
Definition: nuklear.h:4021
struct nk_style_item normal
Definition: nuklear.h:5015
struct nk_vec2i begin
Definition: nuklear.h:4338
struct nk_buffer buffer
Definition: nuklear.h:4089
struct nk_vec2i a
Definition: nuklear.h:4382
struct nk_style_item active
Definition: nuklear.h:4880
struct nk_style_edit edit
Definition: nuklear.h:5149
NK_API int nk_window_is_any_hovered(struct nk_context *)
NK_API struct nk_vec2 nk_vec2iv(const int *xy)
unsigned short h
Definition: nuklear.h:4332
unsigned char cursor_at_end_of_line
Definition: nuklear.h:4214
NK_API int nk_combo_begin_text(struct nk_context *, const char *selected, int, struct nk_vec2 size)
#define NK_BUTTON_BEHAVIOR_STACK_SIZE
Definition: nuklear.h:5381
struct nk_style_button dec_button
Definition: nuklear.h:4866
NK_API void nk_input_glyph(struct nk_context *, const nk_glyph)
struct nk_style_item pressed_active
Definition: nuklear.h:4811
void(* nk_plugin_paste)(nk_handle, struct nk_text_edit *)
Definition: nuklear.h:482
nk_button_behavior
Definition: nuklear.h:467
NK_API struct nk_vec2 nk_layout_space_to_screen(struct nk_context *, struct nk_vec2)
struct nk_vec2 label_padding
Definition: nuklear.h:5091
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:4931
NK_API int nk_style_pop_float(struct nk_context *)
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:4873
NK_API struct nk_rect nk_layout_space_bounds(struct nk_context *)
float min_row_height_padding
Definition: nuklear.h:5116
struct nk_table * prev
Definition: nuklear.h:5457
NK_API int nk_button_image_text_styled(struct nk_context *, const struct nk_style_button *, struct nk_image img, const char *, int, nk_flags alignment)
NK_API int nk_init_custom(struct nk_context *, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font *)
struct nk_vec2i points[1]
Definition: nuklear.h:4433
struct nk_style_tab tab
Definition: nuklear.h:5153
void(* draw_begin)(struct nk_command_buffer *, nk_handle userdata)
Definition: nuklear.h:4768
struct nk_color border_color
Definition: nuklear.h:4777
NK_API int nk_select_symbol_text(struct nk_context *, enum nk_symbol_type, const char *, int, nk_flags align, int value)
NK_API enum nk_widget_layout_states nk_widget_fitting(struct nk_rect *, struct nk_context *, struct nk_vec2)
NK_API double nk_strtod(const char *str, const char **endptr)
struct nk_window win
Definition: nuklear.h:5463
NK_API void nk_window_close(struct nk_context *ctx, const char *name)
int(* nk_plugin_filter)(const struct nk_text_edit *, nk_rune unicode)
Definition: nuklear.h:481
struct nk_clipboard clip
Definition: nuklear.h:4205
nk_style_cursor
Definition: nuklear.h:3516
struct nk_window * begin
Definition: nuklear.h:5521
NK_API void nk_style_default(struct nk_context *)
NK_API void nk_input_scroll(struct nk_context *, struct nk_vec2 val)
NK_API int nk_input_has_mouse_click_down_in_rect(const struct nk_input *, enum nk_buttons, struct nk_rect, int down)
#define NK_FLOAT_STACK_SIZE
Definition: nuklear.h:5393
struct nk_style_item cursor_hover
Definition: nuklear.h:4911
float y
Definition: nuklear.h:5200
NK_API void nk_free(struct nk_context *)
struct nk_color text_normal
Definition: nuklear.h:4950
unsigned short point_count
Definition: nuklear.h:4447
NK_API char * nk_str_at_char(struct nk_str *, int pos)
NK_API int nk_button_label_styled(struct nk_context *, const struct nk_style_button *, const char *title)
NK_API struct nk_color nk_rgb(int r, int g, int b)
NK_API int nk_tree_push_hashed(struct nk_context *, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, const char *hash, int len, int seed)
enum nk_symbol_type sym_active
Definition: nuklear.h:5034
NK_API void nk_layout_space_push(struct nk_context *, struct nk_rect bounds)
NK_API void nk_combobox_separator(struct nk_context *, const char *items_separated_by_separator, int separator, int *selected, int count, int item_height, struct nk_vec2 size)
unsigned int has_scrolling
Definition: nuklear.h:5255
int len
Definition: nuklear.h:4090
unsigned int type
Definition: nuklear.h:4018
NK_API void nk_tree_state_pop(struct nk_context *)
NK_API int nk_combo_begin_label(struct nk_context *, const char *selected, struct nk_vec2 size)
NK_API int nk_stricmpn(const char *s1, const char *s2, int n)
#define NK_UINT32
Definition: nuklear.h:360
unsigned int table_count
Definition: nuklear.h:5347
NK_API int nk_style_push_flags(struct nk_context *, nk_flags *, nk_flags)
struct nk_style_item active
Definition: nuklear.h:5017
NK_API void nk_window_collapse_if(struct nk_context *, const char *name, enum nk_collapse_states, int cond)
struct nk_vec2 button_padding
Definition: nuklear.h:5040
float contextual_border
Definition: nuklear.h:5111
char text[NK_INPUT_MAX]
Definition: nuklear.h:4545
NK_API void nk_layout_reset_min_row_height(struct nk_context *)
nk_uint y
Definition: nuklear.h:464
NK_API struct nk_colorf nk_color_cf(struct nk_color)
unsigned char active
Definition: nuklear.h:4218
float templates[NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS]
Definition: nuklear.h:5229
NK_API void nk_buffer_push(struct nk_buffer *, enum nk_buffer_allocation_type type, const void *memory, nk_size size, nk_size align)
NK_API struct nk_vec2 nk_window_get_position(const struct nk_context *ctx)
NK_API void nk_color_fv(float *rgba_out, struct nk_color)
NK_API int nk_input_is_mouse_prev_hovering_rect(const struct nk_input *, struct nk_rect)
nk_keys
Definition: nuklear.h:732
unsigned arc_segment_count
Definition: nuklear.h:1149
#define NK_INT16
Definition: nuklear.h:344
struct nk_command header
Definition: nuklear.h:4452
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:4799
NK_API void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols)
nk_style_item_type
Definition: nuklear.h:4725
const struct nk_cursor * cursor_active
Definition: nuklear.h:5135
unsigned circle_segment_count
Definition: nuklear.h:1148
enum nk_symbol_type dec_symbol
Definition: nuklear.h:4868
struct nk_command header
Definition: nuklear.h:4380
struct nk_command header
Definition: nuklear.h:4330
#define NK_LIB
Definition: nuklear.h:264
struct nk_color label_hover
Definition: nuklear.h:5085
enum nk_symbol_type maximize_symbol
Definition: nuklear.h:5081
struct nk_vec2i b
Definition: nuklear.h:4383
struct nk_style_button button
Definition: nuklear.h:5140
struct nk_style_scrollbar scrollh
Definition: nuklear.h:5151
NK_API int nk_input_is_mouse_click_in_rect(const struct nk_input *, enum nk_buttons, struct nk_rect)
NK_API void nk_group_scrolled_end(struct nk_context *)
nk_handle userdata
Definition: nuklear.h:4930
unsigned active_con
Definition: nuklear.h:5298
const float * ratio
Definition: nuklear.h:5222
NK_API int nk_contextual_item_symbol_label(struct nk_context *, enum nk_symbol_type, const char *, nk_flags alignment)
unsigned char single_line
Definition: nuklear.h:4217
struct nk_color foreground
Definition: nuklear.h:4473
struct nk_vec2 padding
Definition: nuklear.h:5123
struct nk_table tbl
Definition: nuklear.h:5461
struct nk_panel * parent
Definition: nuklear.h:5261
NK_API void nk_layout_set_min_row_height(struct nk_context *, float height)
struct nk_style_item normal
Definition: nuklear.h:4971
struct nk_vec2 scrollbar
Definition: nuklear.h:4208
NK_API struct nk_vec2 nk_vec2(float x, float y)
unsigned char padding1
Definition: nuklear.h:4219
NK_API void nk_menubar_end(struct nk_context *)
struct nk_vec2 scrollbar_size
Definition: nuklear.h:4964
struct nk_color border_color
Definition: nuklear.h:4750
NK_API void nk_buffer_mark(struct nk_buffer *, enum nk_buffer_allocation_type type)
#define NK_WINDOW_MAX_NAME
Definition: nuklear.h:5268
nk_uint * offset_x
Definition: nuklear.h:5249
struct nk_config_stack_user_font fonts
Definition: nuklear.h:5442
union nk_page_data data
Definition: nuklear.h:5467
NK_API int nk_combo_begin_symbol(struct nk_context *, enum nk_symbol_type, struct nk_vec2 size)
NK_API void nk_image(struct nk_context *, struct nk_image)
float footer_height
Definition: nuklear.h:5252
#define NK_VECTOR_STACK_SIZE
Definition: nuklear.h:5397
struct nk_draw_null_texture null
Definition: nuklear.h:1151
NK_API void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols)
NK_API int nk_strlen(const char *str)
struct nk_style_item normal
Definition: nuklear.h:4937
float height
Definition: nuklear.h:3841
unsigned short rounding
Definition: nuklear.h:4363
NK_API void nk_tree_element_pop(struct nk_context *)
struct nk_page * next
Definition: nuklear.h:5474
NK_API float nk_strtof(const char *str, const char **endptr)
NK_UINT32 nk_uint
Definition: nuklear.h:401
struct nk_vec2 spacing
Definition: nuklear.h:5041
#define NK_SIZE_TYPE
Definition: nuklear.h:375
struct nk_color bar_active
Definition: nuklear.h:4847
struct nk_color cursor_text_normal
Definition: nuklear.h:4946
NK_API struct nk_color nk_rgb_fv(const float *rgb)
NK_API int nk_color_pick(struct nk_context *, struct nk_colorf *, enum nk_color_format)
NK_API int nk_window_is_collapsed(struct nk_context *ctx, const char *name)
int tree_depth
Definition: nuklear.h:5228
NK_API void nk_draw_text(struct nk_command_buffer *, struct nk_rect, const char *text, int len, const struct nk_user_font *, struct nk_color, struct nk_color)
float b
Definition: nuklear.h:455
enum nk_allocation_type type
Definition: nuklear.h:5480
struct nk_command header
Definition: nuklear.h:4444
unsigned int seq
Definition: nuklear.h:5329
struct nk_buffer memory
Definition: nuklear.h:5493
nk_text_align
Definition: nuklear.h:2998
NK_API struct nk_color nk_hsva_iv(const int *hsva)
NK_API void nk_combobox(struct nk_context *, const char **items, int count, int *selected, int item_height, struct nk_vec2 size)
struct nk_scroll scrollbar
Definition: nuklear.h:5310
NK_API void nk_buffer_reset(struct nk_buffer *, enum nk_buffer_allocation_type type)
NK_API int nk_str_insert_text_runes(struct nk_str *, int pos, const nk_rune *, int)
enum nk_symbol_type sym_maximize
Definition: nuklear.h:5056
void(* nk_command_custom_callback)(void *canvas, short x, short y, unsigned short w, unsigned short h, nk_handle callback_data)
Definition: nuklear.h:4459
NK_API void nk_textedit_delete_selection(struct nk_text_edit *)
struct nk_window * end
Definition: nuklear.h:5522
struct nk_rect item
Definition: nuklear.h:5227
NK_API void nk_color_hsva_bv(nk_byte *hsva_out, struct nk_color)
float item_offset
Definition: nuklear.h:5225
struct nk_color text
Definition: nuklear.h:5048
NK_API struct nk_color nk_rgba(int r, int g, int b, int a)
NK_API void * nk_buffer_memory(struct nk_buffer *)
nk_text_edit_type
Definition: nuklear.h:4193
NK_API void nk_textedit_init_fixed(struct nk_text_edit *, void *memory, nk_size size)
NK_API int nk_init_fixed(struct nk_context *, void *memory, nk_size size, const struct nk_user_font *)
unsigned short h
Definition: nuklear.h:4365
#define NK_SATURATE(x)
Definition: nuklear.h:5538
struct nk_style_slider slider
Definition: nuklear.h:5146
struct nk_color label_active
Definition: nuklear.h:4979
NK_API void nk_stroke_curve(struct nk_command_buffer *, float, float, float, float, float, float, float, float, float line_thickness, struct nk_color)
float popup_border
Definition: nuklear.h:5115
NK_API int nk_button_image(struct nk_context *, struct nk_image img)
NK_API struct nk_image nk_subimage_handle(nk_handle, unsigned short w, unsigned short h, struct nk_rect sub_region)
nk_hash name
Definition: nuklear.h:5303
float border
Definition: nuklear.h:5037
nk_size parent
Definition: nuklear.h:5234
NK_API int nk_combo(struct nk_context *, const char **items, int count, int selected, int item_height, struct nk_vec2 size)
nk_byte a
Definition: nuklear.h:454
NK_API struct nk_color nk_rgba_f(float r, float g, float b, float a)
NK_API void nk_str_clear(struct nk_str *)
float rounding
Definition: nuklear.h:5009
#define NK_TEXTEDIT_UNDOCHARCOUNT
Definition: nuklear.h:4167
NK_API const void * nk_buffer_memory_const(const struct nk_buffer *)
#define nk_ptr_add_const(t, p, i)
Definition: nuklear.h:5555
NK_API void nk_buffer_init_fixed(struct nk_buffer *, void *memory, nk_size size)
float x
Definition: nuklear.h:458
NK_API void nk_layout_row_template_begin(struct nk_context *, float row_height)
NK_API void nk_popup_close(struct nk_context *)
NK_API void nk_stroke_line(struct nk_command_buffer *b, float x0, float y0, float x1, float y1, float line_thickness, struct nk_color)
enum nk_symbol_type inc_symbol
Definition: nuklear.h:4926
nk_uint nk_rune
Definition: nuklear.h:407
struct nk_color text_active
Definition: nuklear.h:4756
struct nk_page_element * freelist
Definition: nuklear.h:5483
struct nk_window * next
Definition: nuklear.h:5350
struct nk_vec2 combo_padding
Definition: nuklear.h:5126
NK_API int nk_str_append_text_utf8(struct nk_str *, const char *, int)
struct nk_color text_hover
Definition: nuklear.h:4785
NK_API void nk_text_colored(struct nk_context *, const char *, int, nk_flags, struct nk_color)
struct nk_config_stack_flags flags
Definition: nuklear.h:5440
nk_panel_set
Definition: nuklear.h:5182
unsigned short w
Definition: nuklear.h:4475
float x
Definition: nuklear.h:5200
struct nk_image image
Definition: nuklear.h:4731
float cursor_rounding
Definition: nuklear.h:4893
NK_API int nk_checkbox_flags_text(struct nk_context *, const char *, int, unsigned int *flags, unsigned int value)
NK_API int nk_button_image_styled(struct nk_context *, const struct nk_style_button *, struct nk_image img)
unsigned short line_thickness
Definition: nuklear.h:4345
int total_height
Definition: nuklear.h:2955
NK_API struct nk_rect nk_rect(float x, float y, float w, float h)
struct nk_vec2 touch_padding
Definition: nuklear.h:4764
nk_orientation
Definition: nuklear.h:469
NK_API void nk_style_show_cursor(struct nk_context *)
struct nk_color text_background
Definition: nuklear.h:4822
struct nk_window * prev
Definition: nuklear.h:5351
struct nk_vec2 min_size
Definition: nuklear.h:5121
struct nk_command header
Definition: nuklear.h:4412
struct nk_color color
Definition: nuklear.h:4408
struct nk_style_item normal
Definition: nuklear.h:5072
struct nk_vec2 padding
Definition: nuklear.h:5090
nk_widget_layout_states
Definition: nuklear.h:2967
struct nk_style_scrollbar scrollv
Definition: nuklear.h:5152
NK_API void nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type, struct nk_color, struct nk_color active, int count, float min_value, float max_value)
NK_API struct nk_colorf nk_color_picker(struct nk_context *, struct nk_colorf, enum nk_color_format)
NK_API int nk_style_push_font(struct nk_context *, const struct nk_user_font *)
enum nk_anti_aliasing line_AA
Definition: nuklear.h:1146
NK_API int nk_group_scrolled_offset_begin(struct nk_context *, nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags)
struct nk_style_item active
Definition: nuklear.h:4749
NK_API int nk_tree_element_image_push_hashed(struct nk_context *, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, int *selected, const char *hash, int len, int seed)
nk_collapse_states
Definition: nuklear.h:470
NK_API const char * nk_utf_at(const char *buffer, int length, int index, nk_rune *unicode, int *len)
NK_API int nk_chart_begin_colored(struct nk_context *, enum nk_chart_type, struct nk_color, struct nk_color active, int num, float min, float max)
NK_API void nk_style_hide_cursor(struct nk_context *)
NK_API int nk_menu_begin_image_text(struct nk_context *, const char *, int, nk_flags align, struct nk_image, struct nk_vec2 size)
struct nk_color border_color
Definition: nuklear.h:4842
struct nk_color color
Definition: nuklear.h:4366
NK_API void nk_str_remove_runes(struct nk_str *str, int len)
struct nk_vec2 spacing
Definition: nuklear.h:5119
float item_width
Definition: nuklear.h:5223
#define NK_ALIGN_PTR(x, mask)
Definition: nuklear.h:5576
struct nk_color color
Definition: nuklear.h:4385
int cursor_visible
Definition: nuklear.h:5137
NK_API int nk_widget_has_mouse_click_down(struct nk_context *, enum nk_buttons, int down)
#define NK_CLAMP(i, v, x)
Definition: nuklear.h:301
struct nk_style_combo combo
Definition: nuklear.h:5154
struct nk_style_property property
Definition: nuklear.h:5148
unsigned short region[4]
Definition: nuklear.h:462
NK_API void nk_input_begin(struct nk_context *)
struct nk_window * win
Definition: nuklear.h:5291
struct nk_color contextual_border_color
Definition: nuklear.h:5103
NK_API int nk_option_text(struct nk_context *, const char *, int, int active)
void * ptr
Definition: nuklear.h:461
struct nk_menu_state menu
Definition: nuklear.h:5257
NK_API void nk_stroke_rect(struct nk_command_buffer *, struct nk_rect, float rounding, float line_thickness, struct nk_color)
NK_API int nk_menu_begin_symbol_text(struct nk_context *, const char *, int, nk_flags align, enum nk_symbol_type, struct nk_vec2 size)
NK_API void nk_push_scissor(struct nk_command_buffer *, struct nk_rect)
NK_API const struct nk_command * nk__begin(struct nk_context *)
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:4798
float min_height
Definition: nuklear.h:5220
NK_API nk_flags nk_chart_push_slot(struct nk_context *, float, int)
nk_edit_flags
Definition: nuklear.h:3341
#define NK_INBOX(px, py, x, y, w, h)
Definition: nuklear.h:5542
#define nk_vec2_sub(a, b)
Definition: nuklear.h:5549
NK_API int nk_str_append_str_char(struct nk_str *, const char *)
float indent
Definition: nuklear.h:5061
struct nk_color selected_color
Definition: nuklear.h:5004
unsigned char initialized
Definition: nuklear.h:4215
NK_API int nk_input_is_key_down(const struct nk_input *, enum nk_keys)
NK_API int nk_window_is_hovered(struct nk_context *)
NK_API double nk_propertyd(struct nk_context *, const char *name, double min, double val, double max, double step, float inc_per_pixel)
#define NK_PI
Definition: nuklear.h:5533
struct nk_cursor * cursor_last
Definition: nuklear.h:5136
NK_API int nk_filter_decimal(const struct nk_text_edit *, nk_rune unicode)
NK_API int nk_filter_binary(const struct nk_text_edit *, nk_rune unicode)
NK_API int nk_init(struct nk_context *, struct nk_allocator *, const struct nk_user_font *)
NK_API int nk_radio_label(struct nk_context *, const char *, int *active)
struct nk_vec2 spacing
Definition: nuklear.h:5092
NK_API void nk_contextual_close(struct nk_context *)
NK_API int nk_input_has_mouse_click_in_rect(const struct nk_input *, enum nk_buttons, struct nk_rect)
NK_API void nk_textedit_init(struct nk_text_edit *, struct nk_allocator *, nk_size size)
const struct nk_cursor * cursors[NK_CURSOR_COUNT]
Definition: nuklear.h:5134
struct nk_vec2 spacing
Definition: nuklear.h:4860
const struct nk_draw_vertex_layout_element * vertex_layout
Definition: nuklear.h:1152
struct nk_style_chart chart
Definition: nuklear.h:5150
#define NK_UTF_SIZE
Definition: nuklear.h:232
struct nk_vec2 popup_padding
Definition: nuklear.h:5125
NK_API void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols)
NK_API void nk_fill_arc(struct nk_command_buffer *, float cx, float cy, float radius, float a_min, float a_max, struct nk_color)
NK_API const char * nk_str_get_const(const struct nk_str *)
NK_API int nk_textedit_cut(struct nk_text_edit *)
NK_API void nk_property_double(struct nk_context *, const char *name, double min, double *val, double max, double step, float inc_per_pixel)
struct nk_color cursor_text_hover
Definition: nuklear.h:4947
NK_API int nk_button_image_label_styled(struct nk_context *, const struct nk_style_button *, struct nk_image img, const char *, nk_flags text_alignment)
NK_API int nk_combo_separator(struct nk_context *, const char *items_separated_by_separator, int separator, int selected, int count, int item_height, struct nk_vec2 size)
NK_API void nk_color_hsva_i(int *h, int *s, int *v, int *a, struct nk_color)
float rounding
Definition: nuklear.h:4857
NK_API void nk_stroke_polyline(struct nk_command_buffer *, float *points, int point_count, float line_thickness, struct nk_color col)
NK_API void nk_text_wrap_colored(struct nk_context *, const char *, int, struct nk_color)
NK_API enum nk_widget_layout_states nk_widget(struct nk_rect *, const struct nk_context *)
nk_edit_events
Definition: nuklear.h:3362
NK_API struct nk_vec2 nk_rect_pos(struct nk_rect)
struct nk_text_undo_state undo
Definition: nuklear.h:4221
NK_API int nk_input_is_mouse_released(const struct nk_input *, enum nk_buttons)
NK_API void nk_property_int(struct nk_context *, const char *name, int min, int *val, int max, int step, float inc_per_pixel)
struct nk_style_button button
Definition: nuklear.h:5031
#define NK_SCROLLBAR_HIDING_TIMEOUT
Definition: nuklear.h:240
enum nk_symbol_type sym_right
Definition: nuklear.h:4983
NK_API struct nk_colorf nk_hsva_colorf(float h, float s, float v, float a)
NK_API void nk_color_hex_rgba(char *output, struct nk_color)
#define NK_MIN(a, b)
Definition: nuklear.h:299
struct nk_vec2 group_padding
Definition: nuklear.h:5124
nk_handle userdata
Definition: nuklear.h:486
NK_API void nk_style_load_cursor(struct nk_context *, enum nk_style_cursor, const struct nk_cursor *)
unsigned int size
Definition: nuklear.h:5473
NK_API int nk_select_symbol_label(struct nk_context *, enum nk_symbol_type, const char *, nk_flags align, int value)
NK_API int nk_input_is_mouse_pressed(const struct nk_input *, enum nk_buttons)
struct nk_style_item cursor_normal
Definition: nuklear.h:4851
#define NK_VALUE_PAGE_CAPACITY
Definition: nuklear.h:5449
NK_API void nk_push_custom(struct nk_command_buffer *, struct nk_rect, nk_command_custom_callback, nk_handle usr)
enum nk_style_header_align align
Definition: nuklear.h:5089
NK_API int nk_str_len_char(struct nk_str *)
unsigned int clicked
Definition: nuklear.h:4541
NK_API int nk_input_any_mouse_click_in_rect(const struct nk_input *, struct nk_rect)
void * ptr
Definition: nuklear.h:4041
NK_API const char * nk_style_get_color_by_name(enum nk_style_colors)
NK_API void nk_stroke_arc(struct nk_command_buffer *, float cx, float cy, float radius, float a_min, float a_max, float line_thickness, struct nk_color)
nk_size vertex_alignment
Definition: nuklear.h:1154
NK_API void nk_tooltip_end(struct nk_context *)
struct nk_color border_color
Definition: nuklear.h:5003
struct nk_style_item cursor_normal
Definition: nuklear.h:4884
unsigned short h
Definition: nuklear.h:4400
short w
Definition: nuklear.h:459
NK_API void nk_spacing(struct nk_context *, int cols)
struct nk_color text_background
Definition: nuklear.h:4753
float y
Definition: nuklear.h:456
NK_API struct nk_color nk_rgba_hex(const char *rgb)
struct nk_vec2i points[1]
Definition: nuklear.h:4440
struct nk_vec2 padding
Definition: nuklear.h:5062
struct nk_command header
Definition: nuklear.h:4437
struct nk_style_item active
Definition: nuklear.h:4973
NK_API int nk_button_symbol_label(struct nk_context *, enum nk_symbol_type, const char *, nk_flags text_alignment)
#define NK_STATIC_ASSERT(exp)
Definition: nuklear.h:288
NK_API struct nk_image nk_subimage_ptr(void *, unsigned short w, unsigned short h, struct nk_rect sub_region)
NK_API void nk_text_wrap(struct nk_context *, const char *, int)
NK_API struct nk_image nk_image_handle(nk_handle)
NK_API struct nk_image nk_image_ptr(void *)
NK_API float nk_window_get_width(const struct nk_context *)
NK_API int nk_image_is_subimage(const struct nk_image *img)
struct nk_command header
Definition: nuklear.h:4362
struct nk_context * ctx
Definition: nuklear.h:2956
unsigned char mode
Definition: nuklear.h:4213
struct nk_style_item hover
Definition: nuklear.h:4840
unsigned short h
Definition: nuklear.h:4475
NK_API void nk_draw_image(struct nk_command_buffer *, struct nk_rect, const struct nk_image *, struct nk_color)
struct nk_color text_hover_active
Definition: nuklear.h:4820
NK_API int nk_selectable_label(struct nk_context *, const char *, nk_flags align, int *value)
struct nk_style_button tab_minimize_button
Definition: nuklear.h:5052
struct nk_vec2 padding
Definition: nuklear.h:4965
NK_API struct nk_color nk_hsva(int h, int s, int v, int a)
struct nk_vec2 spacing
Definition: nuklear.h:5063
#define NK_STYLE_ITEM_STACK_SIZE
Definition: nuklear.h:5389
NK_API int nk_str_insert_text_utf8(struct nk_str *, int pos, const char *, int)
NK_API void nk_tooltip(struct nk_context *, const char *)
struct nk_color text_active
Definition: nuklear.h:4786
#define NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS
Definition: nuklear.h:5166
nk_plugin_alloc alloc
Definition: nuklear.h:487
NK_API void nk_combo_close(struct nk_context *)
struct nk_color text_hover
Definition: nuklear.h:4951
NK_API int nk_radio_text(struct nk_context *, const char *, int, int *active)
NK_API void nk_buffer_clear(struct nk_buffer *)
nk_uint scroll_value
Definition: nuklear.h:2958
short undo_char_point
Definition: nuklear.h:4189
enum nk_symbol_type sym_hover
Definition: nuklear.h:5033
enum nk_symbol_type close_symbol
Definition: nuklear.h:5079
int id
Definition: nuklear.h:461
void *(* nk_plugin_alloc)(nk_handle, void *old, nk_size)
Definition: nuklear.h:479
NK_API struct nk_vec2 nk_window_get_size(const struct nk_context *)
nk_uint * offset_y
Definition: nuklear.h:5250
struct nk_command header
Definition: nuklear.h:4429
struct nk_color label_hover
Definition: nuklear.h:4978
nk_size end
Definition: nuklear.h:5236
int select_end
Definition: nuklear.h:4212
NK_API const char * nk_str_at_char_const(const struct nk_str *, int pos)
struct nk_configuration_stacks stacks
Definition: nuklear.h:5497
struct nk_style_item cursor_active
Definition: nuklear.h:4912
NK_API nk_handle nk_handle_id(int)
NK_API int nk_combo_item_image_label(struct nk_context *, struct nk_image, const char *, nk_flags alignment)
NK_UINT8 nk_uchar
Definition: nuklear.h:396
NK_API struct nk_color nk_rgb_f(float r, float g, float b)
enum nk_allocation_type type
Definition: nuklear.h:4047
float r
Definition: nuklear.h:455
nk_window_flags
Definition: nuklear.h:5272
nk_chart_type
Definition: nuklear.h:472
float x
Definition: nuklear.h:456
struct nk_color symbol_hover
Definition: nuklear.h:5027
struct nk_mouse mouse
Definition: nuklear.h:4551
enum nk_chart_type type
Definition: nuklear.h:5189
struct nk_rect bounds
Definition: nuklear.h:5248
NK_API int nk_contextual_item_label(struct nk_context *, const char *, nk_flags align)
#define NK_CONFIGURATION_STACK_TYPE(prefix, name, type)
Definition: nuklear.h:5408
struct nk_color border_color
Definition: nuklear.h:4907
NK_API int nk_list_view_begin(struct nk_context *, struct nk_list_view *out, const char *id, nk_flags, int row_height, int row_count)
float rounding
Definition: nuklear.h:4962
nk_size size
Definition: nuklear.h:5485
struct nk_vec2 padding
Definition: nuklear.h:4827
NK_API void nk_stroke_polygon(struct nk_command_buffer *, float *, int point_count, float line_thickness, struct nk_color)
unsigned combo_count
Definition: nuklear.h:5296
NK_API void nk_popup_end(struct nk_context *)
unsigned int size
Definition: nuklear.h:5454
int build
Definition: nuklear.h:5518
struct nk_page * pages
Definition: nuklear.h:5482
NK_API void nk_input_motion(struct nk_context *, int x, int y)
NK_API int nk_textedit_paste(struct nk_text_edit *, char const *, int len)
NK_API int nk_utf_len(const char *, int byte_len)
float g
Definition: nuklear.h:455
NK_API void nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, float pad_x, float pad_y, enum nk_heading)
nk_size vertex_size
Definition: nuklear.h:1153
unsigned short w
Definition: nuklear.h:4400
NK_API struct nk_color nk_hsva_fv(const float *hsva)
nk_size cap
Definition: nuklear.h:5486
enum nk_symbol_type inc_symbol
Definition: nuklear.h:4867
NK_API void nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color)
struct nk_keyboard keyboard
Definition: nuklear.h:4550
unsigned short rounding
Definition: nuklear.h:4354
#define NK_UINT16
Definition: nuklear.h:347
unsigned short w
Definition: nuklear.h:462
unsigned short w
Definition: nuklear.h:4407
#define NK_TEXTEDIT_UNDOSTATECOUNT
Definition: nuklear.h:4163
NK_API void nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type, int count, float min_value, float max_value)
struct nk_style_scrollbar scrollbar
Definition: nuklear.h:4941
struct nk_color bar_normal
Definition: nuklear.h:4845
nk_flags last_widget_state
Definition: nuklear.h:5495
#define nk_foreach(c, ctx)
Definition: nuklear.h:1200
struct nk_color color
Definition: nuklear.h:5190
struct nk_command header
Definition: nuklear.h:4405
struct nk_style_item normal_active
Definition: nuklear.h:4809
NK_API float nk_window_get_height(const struct nk_context *)
NK_API float nk_widget_height(struct nk_context *)
NK_API int nk_menu_item_image_label(struct nk_context *, struct nk_image, const char *, nk_flags alignment)
NK_API int nk_slide_int(struct nk_context *, int min, int val, int max, int step)
NK_API int nk_filter_oct(const struct nk_text_edit *, nk_rune unicode)
float filled
Definition: nuklear.h:5226
#define NK_LEN(a)
Definition: nuklear.h:5539
NK_API struct nk_rect nk_recta(struct nk_vec2 pos, struct nk_vec2 size)
NK_API int nk_slider_float(struct nk_context *, float min, float *val, float max, float step)
NK_API int nk_window_is_hidden(struct nk_context *, const char *)
NK_API void nk_fill_triangle(struct nk_command_buffer *, float x0, float y0, float x1, float y1, float x2, float y2, struct nk_color)
#define NK_INTERN
Definition: nuklear.h:270
struct nk_command_buffer buffer
Definition: nuklear.h:5336
NK_API int nk_slider_int(struct nk_context *, int min, int *val, int max, int step)
nk_size allocated
Definition: nuklear.h:4020
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:4932
struct nk_vec2i end
Definition: nuklear.h:4339
NK_API int nk_contextual_item_image_label(struct nk_context *, struct nk_image, const char *, nk_flags alignment)
unsigned con_count
Definition: nuklear.h:5297
NK_API void nk_input_button(struct nk_context *, enum nk_buttons, int x, int y, int down)
NK_API int nk_item_is_any_active(struct nk_context *)
NK_API void nk_label_colored_wrap(struct nk_context *, const char *, struct nk_color)
struct nk_style_toggle checkbox
Definition: nuklear.h:5144
NK_API void nk_input_key(struct nk_context *, enum nk_keys, int down)
void(* nk_plugin_free)(nk_handle, void *old)
Definition: nuklear.h:480
NK_API struct nk_style_item nk_style_item_color(struct nk_color)
NK_API void nk_fill_rect(struct nk_command_buffer *, struct nk_rect, float rounding, struct nk_color)
NK_API int nk_button_push_behavior(struct nk_context *, enum nk_button_behavior)
#define nk_ptr_add(t, p, i)
Definition: nuklear.h:5554
NK_API float nk_slide_float(struct nk_context *, float min, float val, float max, float step)
NK_API void nk_color_hsva_fv(float *hsva_out, struct nk_color)
NK_API void nk_fill_polygon(struct nk_command_buffer *, float *, int point_count, struct nk_color)
NK_API int nk_selectable_symbol_label(struct nk_context *, enum nk_symbol_type, const char *, nk_flags align, int *value)
nk_size size
Definition: nuklear.h:4041
NK_API float nk_widget_width(struct nk_context *)
struct nk_color border_color
Definition: nuklear.h:4881
#define nk_vec2_add(a, b)
Definition: nuklear.h:5550
NK_API int nk_input_is_mouse_hovering_rect(const struct nk_input *, struct nk_rect)
float cursor_border
Definition: nuklear.h:4892
NK_API int nk_chart_begin(struct nk_context *, enum nk_chart_type, int num, float min, float max)
NK_API int nk_style_pop_vec2(struct nk_context *)
struct nk_config_stack_style_item style_items
Definition: nuklear.h:5437
NK_API nk_size nk_buffer_total(struct nk_buffer *)
nk_size size
Definition: nuklear.h:4019
NK_API nk_handle nk_handle_ptr(void *)
unsigned short h
Definition: nuklear.h:4464
unsigned int clicked
Definition: nuklear.h:4525
struct nk_style_item cursor_active
Definition: nuklear.h:4853
NK_API void nk_window_show(struct nk_context *, const char *name, enum nk_show_states)
struct nk_style style
Definition: nuklear.h:5492
NK_API void nk_tree_pop(struct nk_context *)
float range
Definition: nuklear.h:5192
const struct nk_user_font * font
Definition: nuklear.h:4471
NK_API void nk_textedit_undo(struct nk_text_edit *)
NK_API unsigned nk_check_flags_text(struct nk_context *, const char *, int, unsigned int flags, unsigned int value)
unsigned int count
Definition: nuklear.h:5526
struct nk_popup_state popup
Definition: nuklear.h:5342
NK_API float nk_layout_ratio_from_pixel(struct nk_context *, float pixel_width)
struct nk_vec2 padding
Definition: nuklear.h:4762
NK_API nk_flags nk_edit_buffer(struct nk_context *, nk_flags, struct nk_text_edit *, nk_plugin_filter)
float y
Definition: nuklear.h:458
short x
Definition: nuklear.h:457
struct nk_color right
Definition: nuklear.h:4376
NK_API int nk_style_pop_style_item(struct nk_context *)
nk_handle userdata
Definition: nuklear.h:3839
struct nk_style_item hover
Definition: nuklear.h:4905
nk_plugin_filter filter
Definition: nuklear.h:4207
struct nk_style_item normal
Definition: nuklear.h:4904
NK_API int nk_checkbox_flags_label(struct nk_context *, const char *, unsigned int *flags, unsigned int value)
struct nk_color symbol_active
Definition: nuklear.h:5028
nk_rune undo_char[NK_TEXTEDIT_UNDOCHARCOUNT]
Definition: nuklear.h:4186
float scrollbar_hiding_timer
Definition: nuklear.h:5338
NK_API struct nk_color nk_rgb_cf(struct nk_colorf c)
NK_API int nk_str_append_str_utf8(struct nk_str *, const char *)
nk_text_alignment
Definition: nuklear.h:3006
#define NK_API
Definition: nuklear.h:259
struct nk_rect bounds
Definition: nuklear.h:5334
unsigned short w
Definition: nuklear.h:4464
NK_API int nk_window_is_active(struct nk_context *, const char *)
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:4833
unsigned short line_thickness
Definition: nuklear.h:4399
struct nk_style_window_header header
Definition: nuklear.h:5096
float global_alpha
Definition: nuklear.h:1145
struct nk_command header
Definition: nuklear.h:4370
struct nk_color color
Definition: nuklear.h:4358
unsigned capacity
Definition: nuklear.h:5484
NK_API int nk_style_push_color(struct nk_context *, struct nk_color *, struct nk_color)
struct nk_vec2 padding
Definition: nuklear.h:5010
NK_API void nk_style_load_all_cursors(struct nk_context *, struct nk_cursor *)
NK_API void nk_window_set_position(struct nk_context *, const char *name, struct nk_vec2 pos)
struct nk_vec2 touch_padding
Definition: nuklear.h:4828
struct nk_color color
Definition: nuklear.h:4430
struct nk_style_item fixed_background
Definition: nuklear.h:5097
nk_byte b
Definition: nuklear.h:454
NK_API int nk_input_has_mouse_click(const struct nk_input *, enum nk_buttons)
NK_API int nk_combo_begin_color(struct nk_context *, struct nk_color color, struct nk_vec2 size)
NK_API void nk_str_free(struct nk_str *)
NK_API int nk_option_label(struct nk_context *, const char *, int active)
nk_size last
Definition: nuklear.h:5235
nk_allocation_type
Definition: nuklear.h:4025
struct nk_vec2i a
Definition: nuklear.h:4390
nk_plugin_paste paste
Definition: nuklear.h:4173
NK_API int nk_combo_begin_image_label(struct nk_context *, const char *selected, struct nk_image, struct nk_vec2 size)
struct nk_color cursor_border_color
Definition: nuklear.h:4913
nk_size next
Definition: nuklear.h:4323
struct nk_color color
Definition: nuklear.h:4438
struct nk_style_item background
Definition: nuklear.h:5046
NK_API void nk_image_color(struct nk_context *, struct nk_image, struct nk_color)
NK_API void nk_textedit_free(struct nk_text_edit *)
struct nk_scroll scrollbar
Definition: nuklear.h:5335
NK_API void nk_color_hsva_iv(int *hsva_out, struct nk_color)
struct nk_buffer * base
Definition: nuklear.h:4487
void(* nk_plugin_copy)(nk_handle, const char *, int len)
Definition: nuklear.h:483
NK_API struct nk_command_buffer * nk_window_get_canvas(struct nk_context *)
NK_API int nk_checkbox_text(struct nk_context *, const char *, int, int *active)
nk_uint nk_hash
Definition: nuklear.h:405
NK_API int nk_str_len(struct nk_str *)
nk_command_type
Definition: nuklear.h:4298
NK_API nk_flags nk_edit_string(struct nk_context *, nk_flags, char *buffer, int *len, int max, nk_plugin_filter)
NK_API void nk_edit_unfocus(struct nk_context *)
unsigned int old
Definition: nuklear.h:5305
nk_size calls
Definition: nuklear.h:4022
struct nk_vec2 pos
Definition: nuklear.h:4530
struct nk_style_item hover
Definition: nuklear.h:4972
void(* nk_query_font_glyph_f)(nk_handle handle, float font_height, struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint)
Definition: nuklear.h:3821
NK_API int nk_combo_item_image_text(struct nk_context *, struct nk_image, const char *, int, nk_flags alignment)
NK_API int nk_combo_begin_symbol_text(struct nk_context *, const char *selected, int, enum nk_symbol_type, struct nk_vec2 size)
#define NK_INPUT_MAX
Definition: nuklear.h:234
NK_API int nk_menu_begin_symbol_label(struct nk_context *, const char *, nk_flags align, enum nk_symbol_type, struct nk_vec2 size)
NK_API void nk_buffer_free(struct nk_buffer *)
struct nk_style_item hover
Definition: nuklear.h:5073
NK_API struct nk_color nk_hsv_f(float h, float s, float v)
nk_hash name
Definition: nuklear.h:5330
void(* draw_end)(struct nk_command_buffer *, nk_handle userdata)
Definition: nuklear.h:4769
struct nk_style_item cursor_active
Definition: nuklear.h:4886
struct nk_color color
Definition: nuklear.h:4401
struct nk_style_item normal
Definition: nuklear.h:4839
NK_API int nk_button_symbol(struct nk_context *, enum nk_symbol_type)
NK_API int nk_checkbox_label(struct nk_context *, const char *, int *active)
int use_pool
Definition: nuklear.h:5519
enum nk_symbol_type minimize_symbol
Definition: nuklear.h:5080
struct nk_vec2 scroll_delta
Definition: nuklear.h:4533
enum nk_panel_type type
Definition: nuklear.h:5292
NK_API int nk_window_is_closed(struct nk_context *, const char *)
struct nk_vec2 padding
Definition: nuklear.h:4791
NK_API int nk_selectable_symbol_text(struct nk_context *, enum nk_symbol_type, const char *, int, nk_flags align, int *value)
NK_API int nk_group_begin(struct nk_context *, const char *title, nk_flags)
struct nk_rect header
Definition: nuklear.h:5299
NK_API void nk_buffer_info(struct nk_memory_status *, struct nk_buffer *)
NK_API const char * nk_str_at_const(const struct nk_str *, int pos, nk_rune *unicode, int *len)
struct nk_color symbol_normal
Definition: nuklear.h:5026
struct nk_vec2 delta
Definition: nuklear.h:4532
#define NK_COLOR_STACK_SIZE
Definition: nuklear.h:5405
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:4997
float row_padding
Definition: nuklear.h:4966
NK_API int nk_tree_element_push_hashed(struct nk_context *, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, int *selected, const char *hash, int len, int seed)
struct nk_style_item normal
Definition: nuklear.h:4774
enum nk_panel_row_layout_type type
Definition: nuklear.h:5217
NK_API void nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color)
#define NK_BETWEEN(x, a, b)
Definition: nuklear.h:5541
NK_API struct nk_rect nk_window_get_bounds(const struct nk_context *ctx)
NK_API void nk_clear(struct nk_context *)
struct nk_color cursor_border_color
Definition: nuklear.h:4887
float w
Definition: nuklear.h:458
struct nk_color border_color
Definition: nuklear.h:4974
NK_API void nk_menu_end(struct nk_context *)
#define NK_CONTAINER_OF(ptr, type, member)
Definition: nuklear.h:5582
NK_API void nk_colorf_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_colorf in)
struct nk_style_item hover
Definition: nuklear.h:4805
NK_API int nk_selectable_image_text(struct nk_context *, struct nk_image, const char *, int, nk_flags align, int *value)
struct nk_style_button minimize_button
Definition: nuklear.h:5078
struct nk_style_item cursor_normal
Definition: nuklear.h:4910
NK_API nk_flags nk_chart_push(struct nk_context *, float)
NK_API unsigned nk_check_flags_label(struct nk_context *, const char *, unsigned int flags, unsigned int value)
NK_API int nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags)
NK_API float nk_propertyf(struct nk_context *, const char *name, float min, float val, float max, float step, float inc_per_pixel)
NK_API int nk_input_is_key_released(const struct nk_input *, enum nk_keys)
struct nk_color cursor_hover
Definition: nuklear.h:4945
struct nk_style_item hover
Definition: nuklear.h:4879
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:4898
enum nk_command_type type
Definition: nuklear.h:4322
float rounding
Definition: nuklear.h:5038
struct nk_style_button inc_button
Definition: nuklear.h:4924
struct nk_color text_active
Definition: nuklear.h:4952
NK_API struct nk_rect nk_widget_bounds(struct nk_context *)
struct nk_config_stack_vec2 vectors
Definition: nuklear.h:5439
float border
Definition: nuklear.h:5059
NK_API void nk_window_show_if(struct nk_context *, const char *name, enum nk_show_states, int cond)
NK_API int nk_tree_image_push_hashed(struct nk_context *, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, const char *hash, int len, int seed)
nk_color_format
Definition: nuklear.h:474
struct nk_command header
Definition: nuklear.h:4470
float combo_border
Definition: nuklear.h:5110
struct nk_color cursor_normal
Definition: nuklear.h:4944
struct nk_command header
Definition: nuklear.h:4462
nk_hash keys[NK_VALUE_PAGE_CAPACITY]
Definition: nuklear.h:5455
NK_API struct nk_color nk_hsv_iv(const int *hsv)
NK_API int nk_menu_begin_image(struct nk_context *, const char *, struct nk_image, struct nk_vec2 size)
struct nk_color popup_border_color
Definition: nuklear.h:5101
NK_API int nk_menu_begin_image_label(struct nk_context *, const char *, nk_flags align, struct nk_image, struct nk_vec2 size)
NK_API int nk_str_insert_at_char(struct nk_str *, int pos, const char *, int)
NK_API int nk_selectable_text(struct nk_context *, const char *, int, nk_flags align, int *value)
NK_UINT16 nk_ushort
Definition: nuklear.h:399
unsigned int old
Definition: nuklear.h:5324
NK_API void nk_window_set_bounds(struct nk_context *, const char *name, struct nk_rect bounds)
nk_size size
Definition: nuklear.h:4059
enum nk_panel_type type
Definition: nuklear.h:5246
NK_API int nk_input_is_mouse_down(const struct nk_input *, enum nk_buttons)
NK_API nk_size nk_prog(struct nk_context *, nk_size cur, nk_size max, int modifyable)
NK_API int nk_filter_float(const struct nk_text_edit *, nk_rune unicode)
struct nk_vec2i begin
Definition: nuklear.h:4346
nk_handle callback_data
Definition: nuklear.h:4465
NK_API void nk_input_end(struct nk_context *)
NK_API int nk_button_pop_behavior(struct nk_context *)
float h
Definition: nuklear.h:458
struct nk_color selected_normal
Definition: nuklear.h:4955
NK_API void nk_layout_row(struct nk_context *, enum nk_layout_format, float height, int cols, const float *ratio)
NK_API void nk_layout_row_template_end(struct nk_context *)
struct nk_style_button dec_button
Definition: nuklear.h:4925
float rounding
Definition: nuklear.h:5118
NK_API struct nk_color nk_hsva_f(float h, float s, float v, float a)
struct nk_style_edit edit
Definition: nuklear.h:4990
NK_API int nk_combo_string(struct nk_context *, const char *items_separated_by_zeros, int selected, int count, int item_height, struct nk_vec2 size)
struct nk_style_toggle option
Definition: nuklear.h:5143
struct nk_panel pan
Definition: nuklear.h:5462
NK_API int nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score)
struct nk_buffer_marker marker[NK_BUFFER_MAX]
Definition: nuklear.h:4043
NK_API int nk_combo_begin_image_text(struct nk_context *, const char *selected, int, struct nk_image, struct nk_vec2 size)
char string[1]
Definition: nuklear.h:4478
nk_plugin_copy copy
Definition: nuklear.h:4174
struct nk_vec2 size offset
Definition: nuklear.h:463
struct nk_style_item normal
Definition: nuklear.h:4878
NK_API int nk_selectable_image_label(struct nk_context *, struct nk_image, const char *, nk_flags align, int *value)
struct nk_style_button node_minimize_button
Definition: nuklear.h:5054
nk_handle userdata
Definition: nuklear.h:4767
unsigned short line_thickness
Definition: nuklear.h:4415
NK_API int nk_check_text(struct nk_context *, const char *, int, int active)
struct nk_text_edit text_edit
Definition: nuklear.h:5513
NK_API int nk_style_push_style_item(struct nk_context *, struct nk_style_item *, struct nk_style_item)
NK_API void nk_textedit_delete(struct nk_text_edit *, int where, int len)
int slot
Definition: nuklear.h:5199
NK_API nk_hash nk_murmur_hash(const void *key, int len, nk_hash seed)
struct nk_style_item active
Definition: nuklear.h:4776
char name_string[NK_WINDOW_MAX_NAME]
Definition: nuklear.h:5331
struct nk_page_element * prev
Definition: nuklear.h:5469
short x
Definition: nuklear.h:459
enum nk_anti_aliasing shape_AA
Definition: nuklear.h:1147
struct nk_rect clip
Definition: nuklear.h:4488
struct nk_panel * layout
Definition: nuklear.h:5337
NK_API int nk_group_scrolled_begin(struct nk_context *, struct nk_scroll *off, const char *title, nk_flags)
NK_API void nk_style_set_font(struct nk_context *, const struct nk_user_font *)
struct nk_color left
Definition: nuklear.h:4373
struct nk_str string
Definition: nuklear.h:4206
nk_handle userdata
Definition: nuklear.h:4995
short redo_char_point
Definition: nuklear.h:4190
struct nk_command header
Definition: nuklear.h:4344
struct nk_clipboard clip
Definition: nuklear.h:5494
NK_API void nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color)
struct nk_vec2 content_padding
Definition: nuklear.h:5039
unsigned short line_thickness
Definition: nuklear.h:4355
enum nk_style_item_type type
Definition: nuklear.h:4736
NK_API void nk_label_colored(struct nk_context *, const char *, nk_flags align, struct nk_color)
struct nk_style_item active
Definition: nuklear.h:5074
struct nk_color text_normal
Definition: nuklear.h:4784
struct nk_color label_hover
Definition: nuklear.h:5022
NK_API int nk_check_label(struct nk_context *, const char *, int active)
struct nk_command header
Definition: nuklear.h:4421
nk_layout_format
Definition: nuklear.h:476
struct nk_color bar_filled
Definition: nuklear.h:4848
NK_API struct nk_color nk_rgba_cf(struct nk_colorf c)
short y
Definition: nuklear.h:457
NK_API void nk_end(struct nk_context *ctx)
NK_API int nk_menu_begin_symbol(struct nk_context *, const char *, enum nk_symbol_type, struct nk_vec2 size)
NK_API int nk_strfilter(const char *text, const char *regexp)
NK_API void nk_combobox_string(struct nk_context *, const char *items_separated_by_zeros, int *selected, int count, int item_height, struct nk_vec2 size)
nk_text_width_f width
Definition: nuklear.h:3843
char buffer[NK_MAX_NUMBER_BUFFER]
Definition: nuklear.h:5317
NK_API char * nk_str_get(struct nk_str *)
NK_UINT8 nk_byte
Definition: nuklear.h:397
#define NK_CHART_MAX_SLOT
Definition: nuklear.h:5169
struct nk_text_undo_record undo_rec[NK_TEXTEDIT_UNDOSTATECOUNT]
Definition: nuklear.h:4185
unsigned short h
Definition: nuklear.h:4357
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:4899
NK_API int nk_str_append_str_runes(struct nk_str *, const nk_rune *)
NK_API struct nk_color nk_rgba_fv(const float *rgba)
struct nk_config_stack_float floats
Definition: nuklear.h:5438
nk_uint x
Definition: nuklear.h:464
struct nk_style_button tab_maximize_button
Definition: nuklear.h:5051
#define NK_UNUSED(x)
Definition: nuklear.h:5537
int down
Definition: nuklear.h:4540
NK_INT16 nk_short
Definition: nuklear.h:398
NK_API struct nk_vec2 nk_window_get_content_region_size(struct nk_context *)
NK_API struct nk_vec2 nk_window_get_content_region_max(struct nk_context *)
NK_API struct nk_rect nk_window_get_content_region(struct nk_context *)
NK_API int nk_select_image_label(struct nk_context *, struct nk_image, const char *, nk_flags align, int value)
float grow_factor
Definition: nuklear.h:4051
struct nk_vec2 uv
Definition: nuklear.h:1142
nk_uint * scroll_pointer
Definition: nuklear.h:2957
NK_API void nk_layout_space_begin(struct nk_context *, enum nk_layout_format, float height, int widget_count)
unsigned int seq
Definition: nuklear.h:5527
nk_text_edit_mode
Definition: nuklear.h:4198
struct nk_config_stack_color colors
Definition: nuklear.h:5441
NK_API int nk_group_begin_titled(struct nk_context *, const char *name, const char *title, nk_flags)
struct nk_edit_state edit
Definition: nuklear.h:5343
struct nk_color label_active
Definition: nuklear.h:5023
NK_API void nk_style_from_table(struct nk_context *, const struct nk_color *)
#define NK_UINT8
Definition: nuklear.h:341
struct nk_input input
Definition: nuklear.h:5491
NK_API int nk_button_label(struct nk_context *, const char *title)
#define NK_MAX(a, b)
Definition: nuklear.h:300
const struct nk_user_font * font
Definition: nuklear.h:5133
enum nk_button_behavior button_behavior
Definition: nuklear.h:5496
NK_API int nk_button_text(struct nk_context *, const char *title, int len)
NK_API void nk_menubar_begin(struct nk_context *)
NK_API int nk_style_push_float(struct nk_context *, float *, float)
#define NK_PTR_TO_UINT(x)
Definition: nuklear.h:5567
#define NK_FONT_STACK_SIZE
Definition: nuklear.h:5385
NK_API int nk_combo_item_label(struct nk_context *, const char *, nk_flags alignment)
NK_API int nk_button_image_label(struct nk_context *, struct nk_image img, const char *, nk_flags text_alignment)
NK_API int nk_button_image_text(struct nk_context *, struct nk_image img, const char *, int, nk_flags alignment)
NK_API void nk_color_hsv_fv(float *hsv_out, struct nk_color)
NK_API int nk_str_insert_str_char(struct nk_str *, int pos, const char *)
struct nk_vec2i points[1]
Definition: nuklear.h:4448
struct nk_vec2 padding
Definition: nuklear.h:4859
NK_API int nk_menu_begin_label(struct nk_context *, const char *, nk_flags align, struct nk_vec2 size)
unsigned char grabbed
Definition: nuklear.h:4535
NK_API void nk_color_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_color)
unsigned char mode
Definition: nuklear.h:5311
NK_API int nk_style_pop_flags(struct nk_context *)
NK_API int nk_button_symbol_text_styled(struct nk_context *, const struct nk_style_button *, enum nk_symbol_type, const char *, int, nk_flags alignment)
NK_API struct nk_color nk_rgb_hex(const char *rgb)
struct nk_style_item hover
Definition: nuklear.h:5016
nk_symbol_type
Definition: nuklear.h:490
NK_API struct nk_color nk_rgb_bv(const nk_byte *rgb)
NK_API int nk_str_insert_str_utf8(struct nk_str *, int pos, const char *)
struct nk_allocator pool
Definition: nuklear.h:4045
NK_API struct nk_image nk_subimage_id(int, unsigned short w, unsigned short h, struct nk_rect sub_region)
struct nk_color text_background
Definition: nuklear.h:4787
NK_API void nk_plot_function(struct nk_context *, enum nk_chart_type, void *userdata, float(*value_getter)(void *user, int index), int count, int offset)
struct nk_vec2 image_padding
Definition: nuklear.h:4763
NK_API nk_rune nk_str_rune_at(const struct nk_str *, int pos)
struct nk_scroll offset
Definition: nuklear.h:5242
NK_API int nk_style_pop_font(struct nk_context *)
struct nk_style_item hover
Definition: nuklear.h:4775
nk_command_clipping
Definition: nuklear.h:4481
unsigned short r
Definition: nuklear.h:4414
int text_len
Definition: nuklear.h:4546
NK_INT32 nk_int
Definition: nuklear.h:400
NK_API int nk_tree_state_push(struct nk_context *, enum nk_tree_type, const char *title, enum nk_collapse_states *state)
float border
Definition: nuklear.h:4961
NK_API void nk_window_set_size(struct nk_context *, const char *name, struct nk_vec2)
NK_API void nk_input_unicode(struct nk_context *, nk_rune)
NK_API void nk_textedit_redo(struct nk_text_edit *)
NK_API void nk_menu_close(struct nk_context *)
NK_API struct nk_vec2 nk_rect_size(struct nk_rect)
struct nk_style_item background
Definition: nuklear.h:5002
NK_API void nk_str_init(struct nk_str *, const struct nk_allocator *, nk_size size)
NK_API struct nk_image nk_image_id(int)
struct nk_color color
Definition: nuklear.h:4417
NK_API int nk_combo_begin_image(struct nk_context *, struct nk_image img, struct nk_vec2 size)
#define nk_vec2_len_sqr(a)
Definition: nuklear.h:5551
struct nk_style_button inc_button
Definition: nuklear.h:4991
struct nk_style_item active
Definition: nuklear.h:4906
struct nk_command header
Definition: nuklear.h:4397
NK_API void nk_color_d(double *r, double *g, double *b, double *a, struct nk_color)
NK_API void nk_combo_end(struct nk_context *)
NK_API int nk_propertyi(struct nk_context *, const char *name, int min, int val, int max, int step, float inc_per_pixel)
nk_size calls
Definition: nuklear.h:4057
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:4834
NK_API void nk_input_char(struct nk_context *, char)
NK_API void nk_color_dv(double *rgba_out, struct nk_color)
struct nk_page_element win[1]
Definition: nuklear.h:5475
#define NK_INTERSECT(x0, y0, w0, h0, x1, y1, w1, h1)
Definition: nuklear.h:5544
NK_API struct nk_vec2 nk_vec2v(const float *xy)
NK_API int nk_tooltip_begin(struct nk_context *, float width)
NK_API struct nk_rect nk_recti(int x, int y, int w, int h)
NK_API struct nk_panel * nk_window_get_panel(struct nk_context *)
struct nk_vec2 menu_padding
Definition: nuklear.h:5128
struct nk_color label_normal
Definition: nuklear.h:4977
nk_size offset
Definition: nuklear.h:4038
nk_show_states
Definition: nuklear.h:471
struct nk_color color
Definition: nuklear.h:4741
struct nk_style_item pressed
Definition: nuklear.h:4806
NK_API int nk_style_pop_color(struct nk_context *)
NK_API struct nk_color nk_rgba_iv(const int *rgba)
unsigned char single_line
Definition: nuklear.h:5312
struct nk_color selected_hover
Definition: nuklear.h:4956
NK_API void nk_chart_end(struct nk_context *)
struct nk_command_buffer * buffer
Definition: nuklear.h:5260
float a
Definition: nuklear.h:455
struct nk_color menu_border_color
Definition: nuklear.h:5104
NK_API int nk_menu_item_symbol_label(struct nk_context *, enum nk_symbol_type, const char *, nk_flags alignment)
Definition: nuklear.h:466
NK_API int nk_combo_begin_symbol_label(struct nk_context *, const char *selected, enum nk_symbol_type, struct nk_vec2 size)
#define NK_ALIGN_PTR_BACK(x, mask)
Definition: nuklear.h:5578
NK_API int nk_style_push_vec2(struct nk_context *, struct nk_vec2 *, struct nk_vec2)
nk_heading
Definition: nuklear.h:466
#define nk_vec2_muls(a, t)
Definition: nuklear.h:5552
nk_style_colors
Definition: nuklear.h:3485
NK_API struct nk_vec2 nk_window_get_content_region_min(struct nk_context *)
NK_API int nk_menu_begin_text(struct nk_context *, const char *title, int title_len, nk_flags align, struct nk_vec2 size)
struct nk_color background
Definition: nuklear.h:4472
struct nk_vec2i end
Definition: nuklear.h:4347
nk_handle userdata
Definition: nuklear.h:4490
NK_API struct nk_rect nk_rectiv(const int *xywh)
unsigned short h
Definition: nuklear.h:462
struct nk_color border_color
Definition: nuklear.h:5047
NK_API struct nk_vec2 nk_widget_size(struct nk_context *)
NK_API void nk_layout_row_push(struct nk_context *, float value)
nk_flags text_alignment
Definition: nuklear.h:4788